├── .gitignore ├── Arduino ├── Microscope │ ├── Lighting.cpp │ ├── Lighting.h │ ├── Microscope.ino │ ├── SerialControl.cpp │ ├── SerialControl.h │ ├── Stage.cpp │ └── Stage.h └── README.md ├── CAD ├── Assembly Image.JPG ├── Bearing Mount Left Bottom.STL ├── Bearing Mount Left Top.STL ├── Bearing Mount Right Bottom.STL ├── BearingMountRightTop.stl ├── Endstop Mount.STL ├── Front Stage Mount.STL ├── Lighting Mount.STL ├── M3 Spacer.STL ├── Optical Components CAD │ ├── 25mm_lens_mount.stl │ ├── adjustable_length_tube.stl │ ├── corner_connector.stl │ ├── female-female_connector.stl │ ├── lighting_mount.stl │ ├── male-male_connector.stl │ └── objective_lens_mount.stl ├── Optics Clamp.STL ├── Pi Camera Mount.STL ├── README.md ├── Solidworks │ ├── 6mm x 150mm Threaded Rod.SLDPRT │ ├── 8mm x 120mm Threaded Rod.SLDPRT │ ├── 8mm x 250mm Rod.SLDPRT │ ├── 8mm x 300mm Smooth Rod.SLDPRT │ ├── Assembly All.SLDASM │ ├── Bearing Mount Left Bottom.SLDPRT │ ├── Bearing Mount Left Top.SLDPRT │ ├── Bearing Mount Left.SLDPRT │ ├── Bearing Mount Right Bottom.SLDPRT │ ├── Bearing Mount Right Top.SLDPRT │ ├── Bearing Mount Right.SLDPRT │ ├── Bearing Mount w. Y Stepper Mount Right.SLDPRT │ ├── Bearing Mount w. Y Stepper Mount.SLDPRT │ ├── Endstop Assembly.SLDASM │ ├── Endstop Mount.SLDPRT │ ├── Flex Shaft Coupler.SLDPRT │ ├── Front Stage Mount.SLDPRT │ ├── LM8UU Linear Bearing.SLDPRT │ ├── Lighting Mount.SLDPRT │ ├── Linear Bearing Mount.SLDPRT │ ├── M3 Spacer.SLDPRT │ ├── Microswitch.SLDPRT │ ├── NEMA 8 Small Stepper Motor.SLDPRT │ ├── Optics Clamp Mk2.SLDPRT │ ├── Optics Tube 20mm.SLDPRT │ ├── Optics Tube 40mm.SLDPRT │ ├── Optics Tube 50mm.SLDPRT │ ├── Pi Camera Mount.SLDPRT │ ├── Sample Clamp Flat.SLDPRT │ ├── Shaft Coupler 4mm-6mm.SLDPRT │ ├── Slide Clamp Body.SLDPRT │ ├── Small Stepper Mount.SLDPRT │ ├── Stage Protector.SLDPRT │ ├── Stage.SLDPRT │ ├── Stepper Motor NEMA 17.SLDPRT │ ├── Structure Assembly.SLDASM │ ├── Support Assembly.SLDASM │ ├── Thread Nut Mount Crossbeams Bottom.SLDPRT │ ├── Thread Nut Mount Crossbeams Top.SLDPRT │ ├── Thread Nut Mount Crossbeams.SLDPRT │ ├── Thread Nut Mount.SLDPRT │ ├── X-Carriage Single Bearing.SLDPRT │ ├── X-Carriage.sldprt │ ├── XY Stage Assembly.SLDASM │ ├── Y-Carriage Left w. Stepper No Pulley.SLDPRT │ ├── Y-Carriage Left w. Stepper and Endstop.SLDPRT │ ├── Y-Carriage Left.sldprt │ ├── Y-Carriage Right w. Endstop.SLDPRT │ ├── Z Stage End Left no Bearing.SLDPRT │ └── Z Stage End Right w. Endstop.SLDPRT ├── Stage Drawing.JPG ├── Stage Protector.STL ├── Thread Nut Mount Bottom.STL ├── Thread Nut Mount Top.STL └── Thumbs.db ├── Docs ├── Focus.jpg ├── Image Placeholder.jpg ├── Linear Translation Stage Tutorial │ ├── Step 1 - Printing the parts │ │ ├── Bearing Mount Left - Bottom.JPG │ │ ├── Bearing Mount Left - Top.JPG │ │ ├── Bearing Mount Right - Bottom.JPG │ │ ├── Bearing Mount Right - Top.JPG │ │ ├── Endstop Mount.JPG │ │ ├── Lead Nut Mount - Bottom.JPG │ │ ├── Lead Nut Mount - Top.JPG │ │ ├── M3 Spacer.JPG │ │ ├── Optics Clamp.JPG │ │ ├── Stage Endpiece.JPG │ │ └── Thumbs.db │ ├── Step 10 - Lead Nut │ │ ├── 10.1 Leadnut Assembly.JPG │ │ ├── 10.2 Leadnut Assembly.JPG │ │ ├── 10.3 Leadnut Assembly.JPG │ │ ├── Thread Nut Hex Hole.JPG │ │ └── Thumbs.db │ ├── Step 11 - Steel Rods │ │ ├── Steel Rods.JPG │ │ └── Thumbs.db │ ├── Step 12 - Bearings │ │ ├── 12.1 Bearing Mount Assembly.JPG │ │ ├── 12.2 Bearing Mount Assembled.JPG │ │ ├── 12.3 Bearing Mount Disassembled.JPG │ │ ├── 12.4 Installing LM8UU.JPG │ │ ├── Bearings in Place.JPG │ │ ├── Structure Complete.JPG │ │ └── Thumbs.db │ ├── Step 13 - Stage Frame │ │ ├── 13.1 Threading Crossbeam.JPG │ │ ├── 13.2 Threading Crossbeam.JPG │ │ ├── 13.3 Threading Crossbeam Part 2.JPG │ │ ├── 13.3 Threading Crossbeam Part 3.JPG │ │ ├── 13.4 Threading Crossbeam Part 4.JPG │ │ ├── 13.5 Horizontals.JPG │ │ └── Thumbs.db │ ├── Step 14 - Stage End Pieces │ │ ├── IMG_1394.JPG │ │ ├── IMG_1395.JPG │ │ ├── IMG_1396.JPG │ │ └── Thumbs.db │ ├── Step 15 - Mounting Stage │ │ ├── IMG_1397.JPG │ │ ├── IMG_1398.JPG │ │ ├── Stage Mounted.JPG │ │ └── Thumbs.db │ ├── Step 16 - Connecting the stepper │ │ ├── Arduino w. Shield.jpeg │ │ ├── Motor Wiring.jpeg │ │ ├── Stacking Headers.jpeg │ │ └── Thumbs.db │ ├── Step 17 - Switches and Input │ │ ├── 17.1 Buttons.JPG │ │ └── 17.2 Microswitch Wiring.JPG │ ├── Step 18 - Software │ │ ├── Arduino IDE.JPG │ │ ├── Simple_Stage.ino │ │ ├── Stepper_Test.ino │ │ └── Thumbs.db │ ├── Step 2 - Base │ │ ├── 2.1.1 T-Brackets with screws.jpeg │ │ ├── 2.1.2 150mm and 60mm.jpeg │ │ ├── 2.1.3 Half of base.jpeg │ │ ├── 2.1.4 Stepper motor mounting plate.jpeg │ │ ├── 2.1.5 Base symmetric.jpeg │ │ ├── Base 1.JPG │ │ ├── Base 2.JPG │ │ ├── Base 3.JPG │ │ ├── OpenBeams for Base.JPG │ │ └── Thumbs.db │ ├── Step 3 - Shaft Clamps │ │ ├── Shaft Clamps Base Complete.JPG │ │ ├── Shaft Clamps.JPG │ │ └── Thumbs.db │ ├── Step 4 - Attach Feet │ │ ├── 4.1 Attaching Feet.JPG │ │ └── Thumbs.db │ ├── Step 5 - Vertical Supports │ │ ├── Thumbs.db │ │ └── Vertical Supports.JPG │ ├── Step 6 - Endstops │ │ ├── Endstop Interior.JPG │ │ ├── Endstops Mounted.JPG │ │ └── Thumbs.db │ ├── Step 7 - Optics Clamp │ │ ├── Optic Clamp Schematic.JPG │ │ ├── Optics Clamp Top.JPG │ │ ├── Thumbs.db │ │ ├── Top Frame Open.JPG │ │ ├── Top Frame w. Shaft Clamps.JPG │ │ └── Top Frame.JPG │ ├── Step 8 - Upper Shaft Clamps │ │ ├── 8.1 Shaft Clamp.JPG │ │ └── Thumbs.db │ └── Step 9 - Stepper Motor │ │ ├── 9.1 Shaft Coupler.JPG │ │ └── Thumbs.db ├── Optics Diagram.jpg ├── Presentation Images │ ├── 3D Printing 1.JPG │ ├── 3D Printing 2.JPG │ ├── 3D Printing 3.JPG │ ├── Cell Count 1.png │ ├── Cell Count 2 Blur.png │ ├── Cell Count 3 - Threshold.png │ ├── Cell Count 4 - Erode.png │ ├── Cell Count 5 - Erode 2.png │ ├── Cell Count 6 - Blob Dectection.png │ ├── Lead-screw.JPG │ ├── MakerBot.JPG │ ├── Microscope Compact.JPG │ ├── Microscope Structure.JPG │ ├── OpenBeams.JPG │ ├── Thumbs.db │ ├── X-Y Stage CAD.JPG │ ├── X-Y Stage Front Elevation.JPG │ ├── X-Y Stage Top Elevation.JPG │ └── X-Y Stage.JPG ├── Thumbs.db ├── chromaticabberation.jpg ├── optical_tube_bolts.jpg ├── optical_tube_pins.jpg ├── ova5647.pdf ├── planoconvex.jpg └── tube40fly.jpg ├── GUI Test ├── GUI_test.py ├── LightingPanel.py ├── NotebookDemo.py ├── PiGUI.py ├── Thumbs.db └── foobar.bmp ├── README.md └── Raspberry Pi ├── CPP ├── README.md ├── autofocus_class.h ├── autofocus_class_initialisation.h ├── edgedetection_class.h ├── edges.cpp ├── focus_everything.cpp ├── focus_everything.h ├── makefile ├── programming_tutorial.pdf ├── programming_tutorial.tex ├── programming_tutorial_2.pdf └── programming_tutorial_2.tex └── Python └── openlabtools-microscope ├── __init__.py ├── interface.py ├── server.py └── tracker.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | bin/ 10 | build/ 11 | develop-eggs/ 12 | dist/ 13 | eggs/ 14 | lib/ 15 | lib64/ 16 | parts/ 17 | sdist/ 18 | var/ 19 | *.egg-info/ 20 | .installed.cfg 21 | *.egg 22 | 23 | # Installer logs 24 | pip-log.txt 25 | pip-delete-this-directory.txt 26 | 27 | # Unit test / coverage reports 28 | .tox/ 29 | .coverage 30 | .cache 31 | nosetests.xml 32 | coverage.xml 33 | 34 | # Translations 35 | *.mo 36 | 37 | # Mr Developer 38 | .mr.developer.cfg 39 | .project 40 | .pydevproject 41 | 42 | # Rope 43 | .ropeproject 44 | 45 | # Django stuff: 46 | *.log 47 | *.pot 48 | 49 | # Sphinx documentation 50 | docs/_build/ 51 | 52 | -------------------------------------------------------------------------------- /Arduino/Microscope/Lighting.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Lighting.cpp - Library for implementing lighting on the OpenLabTools microscope 3 | Written by James Ritchie for OpenLabTools 4 | github.com/OpenLabTools/Microscope 5 | */ 6 | 7 | #include "Arduino.h" 8 | #include 9 | #include "Lighting.h" 10 | 11 | #define RING_PIN 12 12 | #define STAGE_LED 11 13 | 14 | Adafruit_NeoPixel ring = Adafruit_NeoPixel(16, RING_PIN, NEO_GRB + NEO_KHZ800); 15 | 16 | Lighting::Lighting() 17 | { 18 | 19 | } 20 | 21 | void Lighting::begin() 22 | { 23 | ring.begin(); 24 | pinMode(STAGE_LED, OUTPUT); 25 | setStageLEDBrightness(255); 26 | } 27 | 28 | void Lighting::loop() 29 | { 30 | ring.show(); 31 | } 32 | 33 | void Lighting::setRingColour(uint32_t rgb) 34 | { 35 | for(uint16_t i=0;i<16;i++) { 36 | ring.setPixelColor(i, rgb); 37 | } 38 | } 39 | 40 | void Lighting::setRingBrightness(uint8_t b) 41 | { 42 | ring.setBrightness(b); 43 | } 44 | 45 | void Lighting::setStageLEDBrightness(uint8_t b) 46 | { 47 | //analogWrite(DAC0, b); 48 | } 49 | 50 | 51 | -------------------------------------------------------------------------------- /Arduino/Microscope/Lighting.h: -------------------------------------------------------------------------------- 1 | /* 2 | Lighting.h - Library for implementing lighting on the OpenLabTools microscope 3 | Written by James Ritchie for OpenLabTools 4 | github.com/OpenLabTools/Microscope 5 | */ 6 | 7 | #include "Arduino.h" 8 | #include 9 | 10 | #ifndef Lighting_h 11 | #define Lighting_h 12 | 13 | class Lighting 14 | { 15 | public: 16 | Lighting(); 17 | void begin(); 18 | void loop(); 19 | void setRingColour(uint32_t rgb); 20 | void setRingBrightness(uint8_t b); 21 | void setStageLEDBrightness(uint8_t b); 22 | }; 23 | 24 | 25 | #endif 26 | 27 | 28 | -------------------------------------------------------------------------------- /Arduino/Microscope/Microscope.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Microscope.ino - Firmware for the Arduino on the OpenLabTools microscope 3 | Written by James Ritchie for OpenLabTools 4 | github.com/OpenLabTools/Microscope 5 | 6 | */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "LiquidCrystal.h" 12 | #include "SerialControl.h" 13 | #include "Stage.h" 14 | #include "Lighting.h" 15 | #include "TouchScreen.h" 16 | 17 | //Create objects for Microscope functions 18 | SerialControl scontrol = SerialControl(); 19 | Stage stage = Stage(); 20 | Lighting lights = Lighting(); 21 | LiquidCrystal lcd(0); 22 | 23 | //Calls associated functions and passes arguments for each command 24 | void handle_command(char* cmd, char* arg) 25 | { 26 | String cmdString = String(cmd); //Convert to string for endsWith functions 27 | 28 | //Get the axis for stepper commands 29 | char axisC = cmdString.charAt(0); 30 | int axis; 31 | switch(axisC) { 32 | case 'x': 33 | axis = X_STEPPER; 34 | break; 35 | case 'y': 36 | axis = Y_STEPPER; 37 | break; 38 | case 'z': 39 | axis = Z_STEPPER; 40 | break; 41 | } 42 | 43 | if (cmdString.endsWith("_move")) 44 | { 45 | //Relative move 46 | long steps = atol(arg); 47 | stage.Move(axis, steps); 48 | Serial.println("OK"); 49 | } 50 | else if(cmdString.endsWith("_move_to")) 51 | { 52 | //Absolute z move 53 | if(stage.calibrated) 54 | { 55 | 56 | long position = atol(arg); 57 | //Check position is in range 58 | if(position>=0 && position<=stage.getLength(axis)) 59 | { 60 | stage.MoveTo(axis, position); 61 | Serial.println("OK"); 62 | } 63 | else 64 | { 65 | Serial.println("ERR: POSITION OUT OF RANGE"); 66 | } 67 | } 68 | else 69 | { 70 | Serial.println("ERR: NOT CALIBRATED"); 71 | } 72 | } 73 | else if(strcmp("calibrate", cmd)==0) 74 | { 75 | //Calibrate the stage 76 | stage.calibrate(); 77 | Serial.println("OK"); 78 | } 79 | else if(cmdString.endsWith("_get_length")) 80 | { 81 | //Return length if calibrated 82 | if(stage.calibrated) 83 | { 84 | Serial.println(stage.getLength(axis)); 85 | Serial.println("OK"); 86 | } 87 | else 88 | { 89 | Serial.println("ERR: NOT CALIBRATED"); 90 | } 91 | } 92 | else if(cmdString.endsWith("_get_position")) 93 | { 94 | if(stage.calibrated) 95 | { 96 | Serial.println(stage.getPosition(axis)); 97 | Serial.println("OK"); 98 | } 99 | else 100 | { 101 | Serial.println("ERR: NOT CALIBRATED"); 102 | } 103 | } 104 | else if(cmdString.endsWith("_get_distance_to_go")) 105 | { 106 | Serial.println(stage.getDistanceToGo(axis)); 107 | } 108 | else if(strcmp("is_calibrated", cmd)==0) 109 | { 110 | //Test if calibrated 111 | Serial.println(stage.calibrated); 112 | Serial.println("OK"); 113 | } 114 | else if(strcmp("set_ring_colour", cmd)==0) 115 | { 116 | uint32_t colour = strtoul(arg, NULL, 16); 117 | lights.setRingColour(colour); 118 | Serial.println("OK"); 119 | } 120 | else if(strcmp("set_ring_brightness", cmd)==0) 121 | { 122 | uint8_t brightness = atoi(arg); 123 | lights.setRingBrightness(brightness); 124 | Serial.println("OK"); 125 | } 126 | else if(strcmp("set_stage_led_brightness", cmd)==0) 127 | { 128 | uint8_t brightness = atoi(arg); 129 | lights.setStageLEDBrightness(brightness); 130 | Serial.println("OK"); 131 | } 132 | else 133 | { 134 | //Print error message if command unknown. 135 | Serial.println("ERR: UNKNOWN COMMAND"); 136 | } 137 | } 138 | 139 | void setup() { 140 | //Initialize 141 | scontrol.begin(); 142 | stage.begin(); 143 | lights.begin(); 144 | lcd.begin(16,2); 145 | } 146 | 147 | void loop() { 148 | if (scontrol.string_complete) { 149 | handle_command(scontrol.command, scontrol.arg); 150 | // Reset input str 151 | scontrol.string_complete = false; 152 | } 153 | stage.loop(); 154 | lights.loop(); 155 | 156 | 157 | 158 | 159 | } 160 | 161 | void serialEvent() { 162 | //Attach SerialControl to the Serial event 163 | scontrol.serialEvent(); 164 | } 165 | 166 | void serialEventRun(void){ 167 | //Hack to fix broken IDE functionality for Due 168 | if(Serial.available()) serialEvent(); 169 | } 170 | 171 | 172 | -------------------------------------------------------------------------------- /Arduino/Microscope/SerialControl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SerialControl.cpp - Library for implementing serial control on the OpenLabTools microscope 3 | Written by James Ritchie for OpenLabTools 4 | github.com/OpenLabTools/Microscope 5 | */ 6 | #include "Arduino.h" 7 | #include "SerialControl.h" 8 | 9 | #define MAX_LENGTH 40 10 | 11 | SerialControl::SerialControl() 12 | { 13 | 14 | //Initialize variables 15 | string_complete = false; 16 | input_string = (char *)malloc(MAX_LENGTH); 17 | str_pos = 0; 18 | } 19 | 20 | void SerialControl::begin() 21 | { 22 | //Open a serial connection 23 | Serial.begin(9600); 24 | } 25 | 26 | void SerialControl::serialEvent() 27 | { 28 | while (Serial.available()) { 29 | // get the new byte: 30 | char in_char = (char)Serial.read(); 31 | // add it to the inputString: 32 | if ((str_pos 8 | #include 9 | #include "Stage.h" 10 | #include "TouchScreen.h" 11 | 12 | // Create the motor shield objects 13 | Adafruit_MotorShield lower_afms = Adafruit_MotorShield(0x60); 14 | Adafruit_MotorShield upper_afms = Adafruit_MotorShield(0x61); 15 | 16 | // Create stepper motors for each axis (200 steps per rev) 17 | Adafruit_StepperMotor *xy_a_motor = lower_afms.getStepper(200,1); 18 | Adafruit_StepperMotor *xy_b_motor = lower_afms.getStepper(200,2); 19 | Adafruit_StepperMotor *z_1_motor = upper_afms.getStepper(200, 1); 20 | Adafruit_StepperMotor *z_2_motor = upper_afms.getStepper(200, 2); 21 | 22 | //Create the touchscreen object 23 | TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); 24 | 25 | Stage::Stage() { 26 | //Initialize AccelStepper object with wrapper functions and parameters. 27 | calibrated = false; 28 | 29 | } 30 | 31 | void Stage::begin() 32 | { 33 | //Initiliaze the motor shield 34 | lower_afms.begin(); 35 | upper_afms.begin(); 36 | 37 | //Setup pins for input 38 | pinMode(Z_ULIMIT_SWITCH, INPUT_PULLUP); 39 | pinMode(Z_LLIMIT_SWITCH, INPUT_PULLUP); 40 | 41 | 42 | _x_pos = 0; 43 | _y_pos = 0; 44 | _z_pos = 0; 45 | 46 | _xy_interval = 15; 47 | _z_interval = 15; 48 | 49 | } 50 | 51 | void Stage::loop() 52 | { 53 | 54 | //Check for manual commands 55 | manualControl(); 56 | 57 | //Test limit switches to prevent driving stage past limits 58 | if(!digitalRead(Z_ULIMIT_SWITCH) && (getDistanceToGo(Z_STEPPER) > 0)){ 59 | Move(Z_STEPPER,0); 60 | } 61 | if(!digitalRead(Z_LLIMIT_SWITCH) && (getDistanceToGo(Z_STEPPER) < 0)){ 62 | Move(Z_STEPPER,0);; 63 | } 64 | 65 | //Called on every loop to enable non-blocking control of steppers 66 | if((millis()-_z_last_step)>_z_interval){ 67 | if((_z_target-_z_pos)>0){ 68 | z_1_motor->onestep(FORWARD, DOUBLE); 69 | z_2_motor->onestep(FORWARD, DOUBLE); 70 | _z_last_step = millis(); 71 | _z_pos++; 72 | } 73 | else if((_z_target-_z_pos)<0){ 74 | z_1_motor->onestep(BACKWARD, DOUBLE); 75 | z_2_motor->onestep(BACKWARD, DOUBLE); 76 | _z_last_step = millis(); 77 | _z_pos--; 78 | } 79 | } 80 | 81 | if((millis()-_xy_last_step)>_xy_interval){ 82 | 83 | if((_x_target-_x_pos)>0 && (_y_target-_y_pos)>0){ 84 | //Move up and right 85 | xy_a_motor->onestep(FORWARD, INTERLEAVE); 86 | _xy_last_step = millis(); 87 | _x_pos++; 88 | _y_pos++; 89 | } 90 | else if((_x_target-_x_pos)>0 && (_y_target-_y_pos)<0){ 91 | //Move down and right 92 | xy_b_motor->onestep(FORWARD, INTERLEAVE); 93 | _xy_last_step = millis(); 94 | _x_pos++; 95 | _y_pos--; 96 | } 97 | else if((_x_target-_x_pos)<0 && (_y_target-_y_pos)>0){ 98 | //Move up and left 99 | xy_b_motor->onestep(BACKWARD, INTERLEAVE); 100 | _xy_last_step = millis(); 101 | _x_pos--; 102 | _y_pos++; 103 | } 104 | else if((_x_target-_x_pos)<0 && (_y_target-_y_pos)<0){ 105 | //Move down and left 106 | xy_a_motor->onestep(BACKWARD, INTERLEAVE); 107 | _xy_last_step = millis(); 108 | _x_pos--; 109 | _y_pos--; 110 | } 111 | else if((_x_target-_x_pos)==0 && (_y_target-_y_pos)>0){ 112 | //Move up 113 | xy_a_motor->onestep(FORWARD, INTERLEAVE); 114 | xy_b_motor->onestep(BACKWARD, INTERLEAVE); 115 | _xy_last_step = millis(); 116 | _y_pos++; 117 | } 118 | else if((_x_target-_x_pos)==0 && (_y_target-_y_pos)<0){ 119 | //Move down 120 | xy_a_motor->onestep(BACKWARD, INTERLEAVE); 121 | xy_b_motor->onestep(FORWARD, INTERLEAVE); 122 | _xy_last_step = millis(); 123 | _y_pos--; 124 | } 125 | else if((_x_target-_x_pos)>0 && (_y_target-_y_pos)==0){ 126 | //Move right 127 | xy_a_motor->onestep(FORWARD, INTERLEAVE); 128 | xy_b_motor->onestep(FORWARD, INTERLEAVE); 129 | _xy_last_step = millis(); 130 | _x_pos++; 131 | } 132 | else if((_x_target-_x_pos)<0 && (_y_target-_y_pos)==0){ 133 | //Move left 134 | xy_a_motor->onestep(BACKWARD, INTERLEAVE); 135 | xy_b_motor->onestep(BACKWARD, INTERLEAVE); 136 | _xy_last_step = millis(); 137 | _x_pos--; 138 | } 139 | 140 | } 141 | 142 | 143 | } 144 | 145 | void Stage::manualControl() 146 | { 147 | //Get pressure point from TS. 148 | p = ts.getPoint(); 149 | 150 | if(p.z > 10){ 151 | //If pressed, move stage depending on sector 152 | if(p.y<400 && p.x>600){ 153 | //Move forwards 154 | _y_target = _y_pos - 1; 155 | } 156 | 157 | if(p.y>700 && p.x>600){ 158 | //Move backwards 159 | _y_target = _y_pos + 1; 160 | } 161 | 162 | if(p.x<700 &&p.x>380&&p.y>450&&p.y<650){ 163 | //Move right 164 | _x_target = _x_pos + 1; 165 | } 166 | 167 | if(p.x>750&&p.y>450&&p.y<650){ 168 | //Move left 169 | _x_target = _x_pos - 1; 170 | } 171 | 172 | if(p.x<310 && p.y<500){ 173 | //Move up 174 | _z_target = _z_pos + 1; 175 | } 176 | 177 | if(p.x<310 && p.y>500){ 178 | //Move down 179 | _z_target = _z_pos - 1; 180 | } 181 | } 182 | 183 | 184 | } 185 | 186 | void Stage::calibrate() 187 | { 188 | 189 | } 190 | 191 | long Stage::getPosition(int stepper) 192 | { 193 | if(calibrated) 194 | { 195 | switch(stepper) { 196 | case X_STEPPER: 197 | return _x_pos; 198 | break; 199 | case Y_STEPPER: 200 | return _y_pos; 201 | break; 202 | case Z_STEPPER: 203 | return _z_pos; 204 | break; 205 | } 206 | } 207 | } 208 | 209 | long Stage::getDistanceToGo(int stepper) 210 | { 211 | switch(stepper) { 212 | case X_STEPPER: 213 | return _x_target - _x_pos; 214 | break; 215 | case Y_STEPPER: 216 | return _y_target - _y_pos; 217 | break; 218 | case Z_STEPPER: 219 | return _z_target - _z_pos; 220 | break; 221 | } 222 | } 223 | 224 | long Stage::getLength(int stepper) 225 | { 226 | switch(stepper) { 227 | case X_STEPPER: 228 | return _x_length; 229 | break; 230 | case Y_STEPPER: 231 | return _y_length; 232 | break; 233 | case Z_STEPPER: 234 | return _z_length; 235 | break; 236 | } 237 | } 238 | 239 | void Stage::Move(int stepper, long steps) 240 | { 241 | switch(stepper) { 242 | case X_STEPPER: 243 | _x_target = _x_pos + steps; 244 | break; 245 | case Y_STEPPER: 246 | _y_target = _y_pos + steps; 247 | break; 248 | case Z_STEPPER: 249 | _z_target = _z_pos + steps; 250 | break; 251 | } 252 | } 253 | 254 | void Stage::MoveTo(int stepper, long position) 255 | { 256 | //Move the z stepper to a position 257 | if(calibrated){ 258 | switch(stepper) { 259 | case X_STEPPER: 260 | _x_target = position; 261 | break; 262 | case Y_STEPPER: 263 | _y_target = position; 264 | break; 265 | case Z_STEPPER: 266 | _z_target = position; 267 | break; 268 | } 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /Arduino/Microscope/Stage.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stage.h - Library for controlling the stage on the OpenLabTools microscope 3 | Written by James Ritchie for OpenLabTools 4 | github.com/OpenLabTools/Microscope 5 | */ 6 | #include "Arduino.h" 7 | #include 8 | #include 9 | #include 10 | #include "TouchScreen.h" 11 | 12 | #ifndef Stage_h 13 | #define Stage_h 14 | 15 | //Define pins 16 | #define Z_ULIMIT_SWITCH 5 17 | #define Z_LLIMIT_SWITCH 4 18 | 19 | //Define motor selections 20 | #define X_STEPPER 0 21 | #define Y_STEPPER 1 22 | #define Z_STEPPER 2 23 | 24 | //Define Touchscreen pins 25 | #define YP A2 // must be an analog pin, use "An" notation! 26 | #define XM A3 // must be an analog pin, use "An" notation! 27 | #define YM A0 // can be a digital pin 28 | #define XP A1 // can be a digital pin 29 | 30 | class Stage 31 | { 32 | public: 33 | boolean manual_control; 34 | boolean calibrated; 35 | 36 | Stage(); 37 | 38 | void begin(); 39 | void loop(); 40 | void manualControl(); 41 | 42 | void calibrate(); 43 | 44 | long getPosition(int stepper); 45 | long getDistanceToGo(int stepper); 46 | long getLength(int stepper); 47 | 48 | void Move(int stepper, long steps); 49 | void MoveTo(int stepper,long position); 50 | 51 | 52 | 53 | private: 54 | 55 | long _x_pos; 56 | long _y_pos; 57 | long _z_pos; 58 | 59 | long _x_length; 60 | long _y_length; 61 | long _z_length; 62 | 63 | long _x_target; 64 | long _z_target; 65 | long _y_target; 66 | 67 | long _z_last_step; 68 | long _xy_last_step; 69 | 70 | long _z_interval; 71 | long _xy_interval; 72 | 73 | Point p; 74 | 75 | }; 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /Arduino/README.md: -------------------------------------------------------------------------------- 1 | # Arduino 2 | 3 | ## Commands 4 | 5 | The serial connection takes commands as an ASCII string of the form 6 | 7 | ``` 8 | command argument 9 | ``` 10 | 11 | terminated with a newline(\n). Argument is optional for some commands. The 12 | Arduino will return several lines: 13 | 14 | ``` 15 | Command: command 16 | Argument: argument 17 | Return: value 18 | OK 19 | ``` 20 | 21 | The `Command:` and `Argument:` lines are always returned to confirm receipt of the command. `Return: value` is printed if the command returns a value. 22 | `OK` is returned when the Arduino is ready to receive another command. 23 | All commands except calibrate are asynchronous(i.e the Arduino will start 24 | moving the steppers whilst continuing to receive commands) and so will 25 | return OK almost immediately. 26 | 27 | ### calibrate 28 | 29 | **Command** 30 | 31 | ``` 32 | calibrate 33 | ``` 34 | 35 | **Response** 36 | 37 | ``` 38 | Command: calibrate 39 | Argument: 40 | OK 41 | ``` 42 | 43 | `calibrate` runs the calibration routine for the stage, running the stepper 44 | motors on each axis to find where the limit switches are and establishing 45 | an absolute positioning system. Other commands which rely on absolute 46 | positioning will return an error if this has not been run. 47 | 48 | ### is_calibrated 49 | 50 | **Command** 51 | 52 | ``` 53 | is_calibrated 54 | ``` 55 | 56 | **Response** 57 | 58 | ``` 59 | Command: is_calibrated 60 | Argument: 61 | Return: 1 62 | OK 63 | ``` 64 | 65 | `is_calibrated` returns 1 if `calibrated` has been run, and 0 if not. 66 | 67 | ### get_z_length 68 | 69 | **Command** 70 | 71 | ``` 72 | get_z_length 73 | ``` 74 | 75 | **Response** 76 | 77 | ``` 78 | Command: get__z_length 79 | Argument: 80 | Return: 15381 81 | OK 82 | ``` 83 | 84 | Returns the total length of the z axis in units of steps. 85 | 86 | ### get_z_position 87 | 88 | **Command** 89 | 90 | ``` 91 | get_z_position 92 | ``` 93 | 94 | **Response** 95 | 96 | ``` 97 | Command: get_z_position 98 | Argument: 99 | Return: 3651 100 | OK 101 | ``` 102 | 103 | Returns the current z position of the stage, in units of steps, from the 104 | bottom of the axis. 105 | 106 | ### z_move 107 | 108 | **Command** 109 | 110 | ``` 111 | z_move -500 112 | ``` 113 | 114 | **Response** 115 | 116 | ``` 117 | Command: z_move 118 | Argument: -500 119 | OK 120 | ``` 121 | 122 | Moves the stage from its current position the given number of steps along 123 | the z-axis. Positive for up, negative for down 124 | 125 | ### z__move_to 126 | 127 | **Command** 128 | 129 | ``` 130 | z_move_to 1500 131 | ``` 132 | 133 | **Response** 134 | 135 | ``` 136 | Command: z_move_to 137 | Argument: 1500 138 | OK 139 | ``` 140 | 141 | Moves the stage to an absolute position along the z-axis, measured in 142 | units of steps from the bottom of the axis. If given a position which is out 143 | of the range of the axis (i.e. less than 0 or greater than the result of 144 | `get_z_length`), will return an Out of Range error. 145 | 146 | ### get_z_distance_to_go 147 | 148 | **Command** 149 | 150 | ``` 151 | get_z_distance_to_go 152 | ``` 153 | 154 | **Response** 155 | 156 | ``` 157 | Command: get_z_distance_to_go 158 | Argument: 159 | Return: 130 160 | OK 161 | ``` 162 | 163 | Gets the number of steps to go until the stage reaches its current target on 164 | the z-axis(set by `z_move` or `z_move_to`). 165 | -------------------------------------------------------------------------------- /CAD/Assembly Image.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Assembly Image.JPG -------------------------------------------------------------------------------- /CAD/Bearing Mount Left Bottom.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Bearing Mount Left Bottom.STL -------------------------------------------------------------------------------- /CAD/Bearing Mount Left Top.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Bearing Mount Left Top.STL -------------------------------------------------------------------------------- /CAD/Bearing Mount Right Bottom.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Bearing Mount Right Bottom.STL -------------------------------------------------------------------------------- /CAD/Endstop Mount.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Endstop Mount.STL -------------------------------------------------------------------------------- /CAD/Front Stage Mount.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Front Stage Mount.STL -------------------------------------------------------------------------------- /CAD/Lighting Mount.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Lighting Mount.STL -------------------------------------------------------------------------------- /CAD/M3 Spacer.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/M3 Spacer.STL -------------------------------------------------------------------------------- /CAD/Optical Components CAD/25mm_lens_mount.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Optical Components CAD/25mm_lens_mount.stl -------------------------------------------------------------------------------- /CAD/Optical Components CAD/adjustable_length_tube.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Optical Components CAD/adjustable_length_tube.stl -------------------------------------------------------------------------------- /CAD/Optical Components CAD/corner_connector.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Optical Components CAD/corner_connector.stl -------------------------------------------------------------------------------- /CAD/Optical Components CAD/female-female_connector.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Optical Components CAD/female-female_connector.stl -------------------------------------------------------------------------------- /CAD/Optical Components CAD/lighting_mount.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Optical Components CAD/lighting_mount.stl -------------------------------------------------------------------------------- /CAD/Optical Components CAD/male-male_connector.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Optical Components CAD/male-male_connector.stl -------------------------------------------------------------------------------- /CAD/Optical Components CAD/objective_lens_mount.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Optical Components CAD/objective_lens_mount.stl -------------------------------------------------------------------------------- /CAD/Optics Clamp.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Optics Clamp.STL -------------------------------------------------------------------------------- /CAD/Pi Camera Mount.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Pi Camera Mount.STL -------------------------------------------------------------------------------- /CAD/README.md: -------------------------------------------------------------------------------- 1 | CAD 2 | === 3 | 4 | This folder contains the CAD files for the microscope. -------------------------------------------------------------------------------- /CAD/Solidworks/6mm x 150mm Threaded Rod.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/6mm x 150mm Threaded Rod.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/8mm x 120mm Threaded Rod.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/8mm x 120mm Threaded Rod.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/8mm x 250mm Rod.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/8mm x 250mm Rod.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/8mm x 300mm Smooth Rod.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/8mm x 300mm Smooth Rod.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Assembly All.SLDASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Assembly All.SLDASM -------------------------------------------------------------------------------- /CAD/Solidworks/Bearing Mount Left Bottom.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Bearing Mount Left Bottom.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Bearing Mount Left Top.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Bearing Mount Left Top.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Bearing Mount Left.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Bearing Mount Left.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Bearing Mount Right Bottom.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Bearing Mount Right Bottom.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Bearing Mount Right Top.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Bearing Mount Right Top.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Bearing Mount Right.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Bearing Mount Right.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Bearing Mount w. Y Stepper Mount Right.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Bearing Mount w. Y Stepper Mount Right.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Bearing Mount w. Y Stepper Mount.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Bearing Mount w. Y Stepper Mount.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Endstop Assembly.SLDASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Endstop Assembly.SLDASM -------------------------------------------------------------------------------- /CAD/Solidworks/Endstop Mount.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Endstop Mount.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Flex Shaft Coupler.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Flex Shaft Coupler.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Front Stage Mount.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Front Stage Mount.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/LM8UU Linear Bearing.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/LM8UU Linear Bearing.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Lighting Mount.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Lighting Mount.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Linear Bearing Mount.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Linear Bearing Mount.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/M3 Spacer.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/M3 Spacer.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Microswitch.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Microswitch.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/NEMA 8 Small Stepper Motor.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/NEMA 8 Small Stepper Motor.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Optics Clamp Mk2.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Optics Clamp Mk2.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Optics Tube 20mm.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Optics Tube 20mm.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Optics Tube 40mm.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Optics Tube 40mm.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Optics Tube 50mm.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Optics Tube 50mm.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Pi Camera Mount.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Pi Camera Mount.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Sample Clamp Flat.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Sample Clamp Flat.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Shaft Coupler 4mm-6mm.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Shaft Coupler 4mm-6mm.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Slide Clamp Body.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Slide Clamp Body.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Small Stepper Mount.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Small Stepper Mount.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Stage Protector.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Stage Protector.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Stage.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Stage.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Stepper Motor NEMA 17.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Stepper Motor NEMA 17.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Structure Assembly.SLDASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Structure Assembly.SLDASM -------------------------------------------------------------------------------- /CAD/Solidworks/Support Assembly.SLDASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Support Assembly.SLDASM -------------------------------------------------------------------------------- /CAD/Solidworks/Thread Nut Mount Crossbeams Bottom.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Thread Nut Mount Crossbeams Bottom.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Thread Nut Mount Crossbeams Top.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Thread Nut Mount Crossbeams Top.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Thread Nut Mount Crossbeams.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Thread Nut Mount Crossbeams.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Thread Nut Mount.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Thread Nut Mount.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/X-Carriage Single Bearing.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/X-Carriage Single Bearing.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/X-Carriage.sldprt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/X-Carriage.sldprt -------------------------------------------------------------------------------- /CAD/Solidworks/XY Stage Assembly.SLDASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/XY Stage Assembly.SLDASM -------------------------------------------------------------------------------- /CAD/Solidworks/Y-Carriage Left w. Stepper No Pulley.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Y-Carriage Left w. Stepper No Pulley.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Y-Carriage Left w. Stepper and Endstop.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Y-Carriage Left w. Stepper and Endstop.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Y-Carriage Left.sldprt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Y-Carriage Left.sldprt -------------------------------------------------------------------------------- /CAD/Solidworks/Y-Carriage Right w. Endstop.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Y-Carriage Right w. Endstop.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Z Stage End Left no Bearing.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Z Stage End Left no Bearing.SLDPRT -------------------------------------------------------------------------------- /CAD/Solidworks/Z Stage End Right w. Endstop.SLDPRT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Solidworks/Z Stage End Right w. Endstop.SLDPRT -------------------------------------------------------------------------------- /CAD/Stage Drawing.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Stage Drawing.JPG -------------------------------------------------------------------------------- /CAD/Stage Protector.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Stage Protector.STL -------------------------------------------------------------------------------- /CAD/Thread Nut Mount Bottom.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Thread Nut Mount Bottom.STL -------------------------------------------------------------------------------- /CAD/Thread Nut Mount Top.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Thread Nut Mount Top.STL -------------------------------------------------------------------------------- /CAD/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/CAD/Thumbs.db -------------------------------------------------------------------------------- /Docs/Focus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Focus.jpg -------------------------------------------------------------------------------- /Docs/Image Placeholder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Image Placeholder.jpg -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Bearing Mount Left - Bottom.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Bearing Mount Left - Bottom.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Bearing Mount Left - Top.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Bearing Mount Left - Top.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Bearing Mount Right - Bottom.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Bearing Mount Right - Bottom.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Bearing Mount Right - Top.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Bearing Mount Right - Top.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Endstop Mount.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Endstop Mount.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Lead Nut Mount - Bottom.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Lead Nut Mount - Bottom.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Lead Nut Mount - Top.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Lead Nut Mount - Top.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/M3 Spacer.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/M3 Spacer.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Optics Clamp.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Optics Clamp.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Stage Endpiece.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Stage Endpiece.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 1 - Printing the parts/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/10.1 Leadnut Assembly.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/10.1 Leadnut Assembly.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/10.2 Leadnut Assembly.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/10.2 Leadnut Assembly.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/10.3 Leadnut Assembly.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/10.3 Leadnut Assembly.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/Thread Nut Hex Hole.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/Thread Nut Hex Hole.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 10 - Lead Nut/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 11 - Steel Rods/Steel Rods.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 11 - Steel Rods/Steel Rods.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 11 - Steel Rods/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 11 - Steel Rods/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/12.1 Bearing Mount Assembly.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/12.1 Bearing Mount Assembly.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/12.2 Bearing Mount Assembled.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/12.2 Bearing Mount Assembled.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/12.3 Bearing Mount Disassembled.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/12.3 Bearing Mount Disassembled.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/12.4 Installing LM8UU.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/12.4 Installing LM8UU.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/Bearings in Place.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/Bearings in Place.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/Structure Complete.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/Structure Complete.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 12 - Bearings/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.1 Threading Crossbeam.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.1 Threading Crossbeam.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.2 Threading Crossbeam.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.2 Threading Crossbeam.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.3 Threading Crossbeam Part 2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.3 Threading Crossbeam Part 2.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.3 Threading Crossbeam Part 3.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.3 Threading Crossbeam Part 3.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.4 Threading Crossbeam Part 4.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.4 Threading Crossbeam Part 4.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.5 Horizontals.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/13.5 Horizontals.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 13 - Stage Frame/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 14 - Stage End Pieces/IMG_1394.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 14 - Stage End Pieces/IMG_1394.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 14 - Stage End Pieces/IMG_1395.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 14 - Stage End Pieces/IMG_1395.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 14 - Stage End Pieces/IMG_1396.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 14 - Stage End Pieces/IMG_1396.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 14 - Stage End Pieces/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 14 - Stage End Pieces/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 15 - Mounting Stage/IMG_1397.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 15 - Mounting Stage/IMG_1397.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 15 - Mounting Stage/IMG_1398.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 15 - Mounting Stage/IMG_1398.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 15 - Mounting Stage/Stage Mounted.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 15 - Mounting Stage/Stage Mounted.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 15 - Mounting Stage/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 15 - Mounting Stage/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 16 - Connecting the stepper/Arduino w. Shield.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 16 - Connecting the stepper/Arduino w. Shield.jpeg -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 16 - Connecting the stepper/Motor Wiring.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 16 - Connecting the stepper/Motor Wiring.jpeg -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 16 - Connecting the stepper/Stacking Headers.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 16 - Connecting the stepper/Stacking Headers.jpeg -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 16 - Connecting the stepper/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 16 - Connecting the stepper/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 17 - Switches and Input/17.1 Buttons.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 17 - Switches and Input/17.1 Buttons.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 17 - Switches and Input/17.2 Microswitch Wiring.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 17 - Switches and Input/17.2 Microswitch Wiring.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 18 - Software/Arduino IDE.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 18 - Software/Arduino IDE.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 18 - Software/Simple_Stage.ino: -------------------------------------------------------------------------------- 1 | // Include the required libraries 2 | #include 3 | #include 4 | #include "utility/Adafruit_PWMServoDriver.h" 5 | 6 | // Define constants for the input pins 7 | #define UP_BUTTON 0 8 | #define DOWN_BUTTON 1 9 | #define TOP_ENDSTOP 2 10 | #define BOTTOM_ENDSTOP 3 11 | 12 | // Create the motor shield object 13 | Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 14 | 15 | // Create the stepper motor object 16 | Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2); 17 | 18 | void setup() 19 | { 20 | // Create the link to the motor shield at the default frequency (1Hz) 21 | AFMS.begin(); 22 | 23 | // Set the speed of the motor in rpm 24 | myMotor->setSpeed(100); 25 | 26 | // Set up inputs 27 | pinMode(UP_BUTTON, INPUT); 28 | pinMode(DOWN_BUTTON, INPUT); 29 | pinMode(TOP_ENDSTOP, INPUT); 30 | pinMode(BOTTOM_ENDSTOP, INPUT); 31 | 32 | } 33 | 34 | void loop() 35 | { 36 | // Get the current states of the buttons 37 | bool up_pressed = digitalRead(UP_BUTTON); 38 | bool down_pressed = digitalRead(DOWN_BUTTON); 39 | 40 | // If both buttons are pressed, do nothing 41 | if(up_pressed && down_pressed) 42 | return; 43 | 44 | // If the up button is pressed and the stage hasn't 45 | // reached the endstop, go up 46 | if(up_pressed && !digitalRead(TOP_ENDSTOP)) 47 | myMotor->step(1, FORWARD, DOUBLE); 48 | 49 | // If the down button is pressed and the stage hasn't 50 | // reached the endstop, go up 51 | if(down_pressed && !digitalRead(TOP_ENDSTOP)) 52 | myMotor->step(1, BACKWARD, DOUBLE); 53 | } 54 | 55 | -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 18 - Software/Stepper_Test.ino: -------------------------------------------------------------------------------- 1 | // Include the required libraries 2 | #include 3 | #include 4 | #include "utility/Adafruit_PWMServoDriver.h" 5 | 6 | // Create the motor shield object 7 | Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 8 | 9 | // Create the stepper motor object 10 | Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2); 11 | 12 | void setup() 13 | { 14 | // Create the link to the motor shield at the default frequency (1Hz) 15 | AFMS.begin(); 16 | 17 | // Set the speed of the motor in rpm 18 | myMotor->setSpeed(100); 19 | } 20 | 21 | void loop() 22 | { 23 | // Run the stepper motor. Parameters are: 24 | // #steps – number of steps 25 | // direction – options are FORWARD or BACKWARD 26 | // steptype – options are SINGLE, DOUBLE, INTERLEAVE or MICROSTEP 27 | myMotor->step(500, FORWARD, DOUBLE); 28 | 29 | // Wait for half a second 30 | delay(500); 31 | 32 | // Run the motor in the opposite direction 33 | myMotor->step(500, FORWARD, DOUBLE); 34 | 35 | // Wait for half a second 36 | delay(500); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 18 - Software/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 18 - Software/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.1 T-Brackets with screws.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.1 T-Brackets with screws.jpeg -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.2 150mm and 60mm.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.2 150mm and 60mm.jpeg -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.3 Half of base.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.3 Half of base.jpeg -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.4 Stepper motor mounting plate.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.4 Stepper motor mounting plate.jpeg -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.5 Base symmetric.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/2.1.5 Base symmetric.jpeg -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/Base 1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/Base 1.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/Base 2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/Base 2.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/Base 3.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/Base 3.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/OpenBeams for Base.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/OpenBeams for Base.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 2 - Base/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 2 - Base/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 3 - Shaft Clamps/Shaft Clamps Base Complete.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 3 - Shaft Clamps/Shaft Clamps Base Complete.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 3 - Shaft Clamps/Shaft Clamps.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 3 - Shaft Clamps/Shaft Clamps.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 3 - Shaft Clamps/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 3 - Shaft Clamps/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 4 - Attach Feet/4.1 Attaching Feet.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 4 - Attach Feet/4.1 Attaching Feet.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 4 - Attach Feet/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 4 - Attach Feet/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 5 - Vertical Supports/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 5 - Vertical Supports/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 5 - Vertical Supports/Vertical Supports.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 5 - Vertical Supports/Vertical Supports.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 6 - Endstops/Endstop Interior.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 6 - Endstops/Endstop Interior.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 6 - Endstops/Endstops Mounted.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 6 - Endstops/Endstops Mounted.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 6 - Endstops/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 6 - Endstops/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Optic Clamp Schematic.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Optic Clamp Schematic.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Optics Clamp Top.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Optics Clamp Top.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Top Frame Open.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Top Frame Open.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Top Frame w. Shaft Clamps.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Top Frame w. Shaft Clamps.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Top Frame.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 7 - Optics Clamp/Top Frame.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 8 - Upper Shaft Clamps/8.1 Shaft Clamp.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 8 - Upper Shaft Clamps/8.1 Shaft Clamp.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 8 - Upper Shaft Clamps/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 8 - Upper Shaft Clamps/Thumbs.db -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 9 - Stepper Motor/9.1 Shaft Coupler.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 9 - Stepper Motor/9.1 Shaft Coupler.JPG -------------------------------------------------------------------------------- /Docs/Linear Translation Stage Tutorial/Step 9 - Stepper Motor/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Linear Translation Stage Tutorial/Step 9 - Stepper Motor/Thumbs.db -------------------------------------------------------------------------------- /Docs/Optics Diagram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Optics Diagram.jpg -------------------------------------------------------------------------------- /Docs/Presentation Images/3D Printing 1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/3D Printing 1.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/3D Printing 2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/3D Printing 2.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/3D Printing 3.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/3D Printing 3.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/Cell Count 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Cell Count 1.png -------------------------------------------------------------------------------- /Docs/Presentation Images/Cell Count 2 Blur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Cell Count 2 Blur.png -------------------------------------------------------------------------------- /Docs/Presentation Images/Cell Count 3 - Threshold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Cell Count 3 - Threshold.png -------------------------------------------------------------------------------- /Docs/Presentation Images/Cell Count 4 - Erode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Cell Count 4 - Erode.png -------------------------------------------------------------------------------- /Docs/Presentation Images/Cell Count 5 - Erode 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Cell Count 5 - Erode 2.png -------------------------------------------------------------------------------- /Docs/Presentation Images/Cell Count 6 - Blob Dectection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Cell Count 6 - Blob Dectection.png -------------------------------------------------------------------------------- /Docs/Presentation Images/Lead-screw.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Lead-screw.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/MakerBot.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/MakerBot.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/Microscope Compact.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Microscope Compact.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/Microscope Structure.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Microscope Structure.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/OpenBeams.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/OpenBeams.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/Thumbs.db -------------------------------------------------------------------------------- /Docs/Presentation Images/X-Y Stage CAD.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/X-Y Stage CAD.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/X-Y Stage Front Elevation.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/X-Y Stage Front Elevation.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/X-Y Stage Top Elevation.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/X-Y Stage Top Elevation.JPG -------------------------------------------------------------------------------- /Docs/Presentation Images/X-Y Stage.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Presentation Images/X-Y Stage.JPG -------------------------------------------------------------------------------- /Docs/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/Thumbs.db -------------------------------------------------------------------------------- /Docs/chromaticabberation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/chromaticabberation.jpg -------------------------------------------------------------------------------- /Docs/optical_tube_bolts.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/optical_tube_bolts.jpg -------------------------------------------------------------------------------- /Docs/optical_tube_pins.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/optical_tube_pins.jpg -------------------------------------------------------------------------------- /Docs/ova5647.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/ova5647.pdf -------------------------------------------------------------------------------- /Docs/planoconvex.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/planoconvex.jpg -------------------------------------------------------------------------------- /Docs/tube40fly.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Docs/tube40fly.jpg -------------------------------------------------------------------------------- /GUI Test/GUI_test.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import wx, os 4 | import NotebookDemo 5 | import time 6 | 7 | class DemoFrame(wx.Frame): 8 | def __init__(self): 9 | """Constructor""" 10 | wx.Frame.__init__(self, None, wx.ID_ANY, 11 | "Microscope Example GUI", 12 | size=(625,1000) 13 | ) 14 | panel = wx.Panel(self) 15 | 16 | 17 | notebook = NotebookDemo.NotebookDemo(panel) 18 | sizer = wx.BoxSizer(wx.VERTICAL) 19 | sizer.Add(notebook, 1, wx.ALL|wx.EXPAND, 5) 20 | panel.SetSizer(sizer) 21 | self.Layout() 22 | self.Move((0,0)) 23 | 24 | self.Show() 25 | 26 | if __name__ == "__main__": 27 | 28 | app = wx.PySimpleApp() 29 | frame = DemoFrame() 30 | app.MainLoop() 31 | -------------------------------------------------------------------------------- /GUI Test/LightingPanel.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import os 3 | import serial 4 | 5 | 6 | maxi = 255 7 | mini = 0 8 | sensitivity = 1 9 | ser = serial.Serial('/dev/ttyUSB0', 9600) 10 | 11 | class LightingPanel(wx.Panel): 12 | """ 13 | This will be the first notebook tab 14 | """ 15 | #---------------------------------------------------------------------- 16 | def __init__(self, parent): 17 | """""" 18 | 19 | wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY) 20 | 21 | 22 | gridsizer = wx.GridBagSizer(5, 25) 23 | 24 | #Panels and Labels 25 | pnl1 = wx.Panel(self, -1, style=wx.SIMPLE_BORDER) 26 | txt1 = wx.StaticText(pnl1, id=-1, label=" LEFT", style=wx.ALIGN_CENTER, name="") 27 | 28 | pnl2 = wx.Panel(self, -1, style=wx.SIMPLE_BORDER) 29 | txt2 = wx.StaticText(pnl2, id=-1, label = " RIGHT", style=wx.ALIGN_CENTER, name="") 30 | 31 | pnl3 = wx.Panel(self, -1, style=wx.SIMPLE_BORDER) 32 | txt3 = wx.StaticText(pnl3, id=-1, label = " FRONT", style=wx.ALIGN_CENTER, name="") 33 | 34 | pnl4 = wx.Panel(self, -1, style=wx.SIMPLE_BORDER) 35 | txt4 = wx.StaticText(pnl4, id=-1, label = " BACK", style=wx.ALIGN_CENTER, name="") 36 | 37 | pnl5 = wx.Panel(self, -1, style=wx.SUNKEN_BORDER) 38 | 39 | 40 | pnl6 = wx.Panel(self, -1, style=wx.NO_BORDER) 41 | 42 | #Buttons 43 | buttonbox = wx.BoxSizer(wx.VERTICAL) 44 | maxbutton = wx.Button(self, 1, 'MAX') 45 | minbutton = wx.Button(self, 2, 'MIN') 46 | self.Bind(wx.EVT_BUTTON, self.gotomax, id = 1) 47 | self.Bind(wx.EVT_BUTTON, self.gotomin, id = 2) 48 | buttonbox.Add(maxbutton, 1) 49 | buttonbox.Add(minbutton, 1) 50 | 51 | #Sensitivity Dropdown Box 52 | #sensitivity_text=wx.StaticText(buttonbox, id=-1, label = "Sensitivity:", style=wx.ALIGN_CENTER, name="") 53 | list1 = ['1x','2x','4x','10x'] 54 | ddbox = wx.ComboBox(self, -1, pos=(50, 170), size=(150, -1), choices=list1, style=wx.CB_READONLY, value="Sensitivity") 55 | self.Bind(wx.EVT_COMBOBOX, self.OnSelection) 56 | buttonbox.Add(ddbox, 1) 57 | 58 | 59 | #Sliders and slider events 60 | self.sld_left = wx.Slider(pnl1, -1, 200, 0, 255, wx.DefaultPosition, 61 | (120,200), wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_INVERSE) 62 | 63 | self.sld_right = wx.Slider(pnl2, -1, 150, 0, 255, wx.DefaultPosition, 64 | (120,200), wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_INVERSE) 65 | 66 | self.sld_front = wx.Slider(pnl3, -1, 200, 0, 255, wx.DefaultPosition, 67 | (120,200), wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_INVERSE) 68 | 69 | self.sld_back = wx.Slider(pnl4, -1, 200, 0, 255, wx.DefaultPosition, 70 | (120,200), wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_INVERSE) 71 | 72 | self.Bind(wx.EVT_SCROLL_CHANGED, self.OnScroll) 73 | 74 | 75 | #Layout Panels in the window 76 | gridsizer.Add(pnl1, (2,0)) 77 | gridsizer.Add(pnl2, (2,2)) 78 | gridsizer.Add(pnl3, (3,1)) 79 | gridsizer.Add(pnl4, (1,1)) 80 | gridsizer.Add(buttonbox, (1,0)) 81 | self.SetSize((750, 1000)) 82 | self.SetSizer(gridsizer) 83 | #self.Centre() 84 | 85 | 86 | 87 | #Events 88 | def OnScroll(self, event): 89 | left_level = chr( self.sld_left.GetValue() / sensitivity ) 90 | right_level = chr( self.sld_right.GetValue() / sensitivity ) 91 | front_level = chr( self.sld_front.GetValue() / sensitivity ) 92 | back_level = chr( self.sld_back.GetValue() / sensitivity ) 93 | 94 | ser.write(left_level) 95 | ser.write(right_level) 96 | ser.write(front_level) 97 | ser.write(back_level) 98 | 99 | def gotomax(self, event): 100 | 101 | for x in range(0,4): 102 | ser.write(chr(maxi / sensitivity)) 103 | 104 | self.sld_left.SetValue(maxi) 105 | self.sld_right.SetValue(maxi) 106 | self.sld_front.SetValue(maxi) 107 | self.sld_back.SetValue(maxi) 108 | 109 | def gotomin(self, event): 110 | for y in range(0,4): 111 | ser.write(chr(mini/sensitivity)) 112 | 113 | self.sld_left.SetValue(mini) 114 | self.sld_right.SetValue(mini) 115 | self.sld_front.SetValue(mini) 116 | self.sld_back.SetValue(mini) 117 | 118 | def OnSelection(self, event): 119 | global sensitivity 120 | sens = event.GetSelection() 121 | 122 | if(sens == 0 ): 123 | sensitivity = 1 124 | 125 | if(sens == 1 ): 126 | sensitivity = 2 127 | 128 | if(sens == 2 ): 129 | sensitivity = 4 130 | 131 | if(sens == 3 ): 132 | sensitivity = 10 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /GUI Test/NotebookDemo.py: -------------------------------------------------------------------------------- 1 | import wx, os 2 | import LightingPanel 3 | import TabPanel 4 | import Panel1 5 | import PiGUI 6 | 7 | class NotebookDemo(wx.Notebook): 8 | """ 9 | Notebook class 10 | """ 11 | 12 | #---------------------------------------------------------------------- 13 | def __init__(self, parent): 14 | wx.Notebook.__init__(self, parent, id=wx.ID_ANY, style= 15 | wx.BK_DEFAULT 16 | #wx.BK_TOP 17 | #wx.BK_BOTTOM 18 | #wx.BK_LEFT 19 | #wx.BK_RIGHT 20 | ) 21 | 22 | # Create the first tab and add it to the notebook 23 | tabOne = LightingPanel.LightingPanel(self) 24 | 25 | self.AddPage(tabOne, "Lighting") 26 | 27 | # Show how to put an image on one of the notebook tabs, 28 | # first make the image list: 29 | il = wx.ImageList(16, 16) 30 | #idx1 = il.Add(images.Smiles.GetBitmap()) 31 | self.AssignImageList(il) 32 | 33 | # now put an image on the first tab we just created: 34 | #self.SetPageImage(0, idx1) 35 | 36 | # Create and add the second tab 37 | #tabTwo = Panel1.Panel1(self,7) 38 | #self.AddPage(tabTwo, "Main") 39 | 40 | # Create and add the third tab 41 | self.AddPage(PiGUI.ViewerPanel(self), "Camera Settings") 42 | 43 | self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged) 44 | self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging) 45 | 46 | 47 | 48 | def OnPageChanged(self, event): 49 | old = event.GetOldSelection() 50 | new = event.GetSelection() 51 | sel = self.GetSelection() 52 | #print 'OnPageChanged, old:%d, new:%d, sel:%d\n' % (old, new, sel) 53 | event.Skip() 54 | 55 | def OnPageChanging(self, event): 56 | old = event.GetOldSelection() 57 | new = event.GetSelection() 58 | sel = self.GetSelection() 59 | #print 'OnPageChanging, old:%d, new:%d, sel:%d\n' % (old, new, sel) 60 | event.Skip() 61 | -------------------------------------------------------------------------------- /GUI Test/PiGUI.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import os 4 | import wx 5 | import subprocess # needed to run external program raspistill 6 | from wx.lib.pubsub import Publisher 7 | 8 | 9 | defaultfilename = 'image.jpg' 10 | 11 | ######################################################################## 12 | class ViewerPanel(wx.Panel): 13 | """ 14 | creates the main screen 15 | """ 16 | 17 | #---------------------------------------------------------------------- 18 | def __init__(self, parent): 19 | """set up for playing with images""" 20 | wx.Panel.__init__(self, parent) 21 | 22 | width, height = wx.DisplaySize() 23 | 24 | bitmap = wx.Bitmap('/home/pi/GUI Test/foobar.bmp') 25 | 26 | control = wx.StaticBitmap(self, -1, bitmap) 27 | control.SetPosition((10,10)) 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /GUI Test/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/GUI Test/Thumbs.db -------------------------------------------------------------------------------- /GUI Test/foobar.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/GUI Test/foobar.bmp -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Microscope 2 | ========== 3 | 4 | OpenLabTools Microscope Project 5 | -------------------------------------------------------------------------------- /Raspberry Pi/CPP/README.md: -------------------------------------------------------------------------------- 1 | Raspberry Pi 2 | ============ 3 | 4 | This file contains the Raspberry Pi-side code for the microscope. -------------------------------------------------------------------------------- /Raspberry Pi/CPP/autofocus_class.h: -------------------------------------------------------------------------------- 1 | // Autofocus Class 2 | 3 | /* This file contains the autofocus class used in the implementation of the autofocusing algorithm. 4 | * The class is quite complex and contains many subsidiary methods and variables that are described in their specific comments underneath, so we won't mention them here. 5 | * For a more comprehensive understanding of all methods of this class read the relevant comments in the whole file. 6 | * Following is a brief description of the main methods of this class. 7 | * 8 | * public: 9 | * Autofocus() -> Constructs the class with default values. 10 | * Autofocus(...) -> Constructs the class with values taken as input at construct time. 11 | * See details of this constructor below. 12 | * ~Autofocus() -> Destroys the class, removing the output folder if required by the user. 13 | * fine_tune() -> Tunes the microscope around the starting point, stopping at the focal point. 14 | * sweep() -> Executes a quick sweep over a long range of movement, taking a few images to find a rough estimate of the focus point position. 15 | * keep_in_focus() -> Recursively checks whether the microscope is in focus and corrects focusing point if wrong. 16 | * test_run(int) -> Executes a test run composed of equally spaced images, saving their focusing value in the file created at class construction. 17 | * Takes the number of images to be taken as input. 18 | * stop_stage(string) -> Verifies if the stage has finished moving before continuing with other operations. 19 | * Takes the command previously sent to move the stage as input. 20 | * 21 | * private: 22 | * algorithm() -> Computes the focusing value of the last image saved. 23 | * greyfy() -> Turns the last image saved into greyscale. 24 | * raspistill_save() -> Saves an image using RaspiStill from terminal. 25 | * remove_picture() -> Deletes the latest image saved. 26 | * remove_folder() -> Deletes the output folder, with all its content. 27 | * move_and_capture(int, int&) -> Moves the stage by a certain number of steps (first input) and takes a picture. 28 | * It then computes the focusing value using algorithm() and stores the position reached in the second input. 29 | * serial_command(...) -> Sends a command to the Arduino through the serial port, and handles the output resulting. 30 | * Read comments on the function for more details. 31 | */ 32 | 33 | #ifndef AUTOFOCUS_CLASS_H 34 | #define AUTOFOCUS_CLASS_H 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "CImg.h" 46 | 47 | using namespace cimg_library; 48 | using namespace std; 49 | using namespace boost::asio; 50 | 51 | 52 | class Autofocus 53 | { 54 | 55 | /* PRIVATE SECTION */ 56 | private: 57 | 58 | // Interaction variables and data storage 59 | io_service m_io; 60 | serial_port m_sp; 61 | vector m_f_values; 62 | ofstream m_values; 63 | boost::asio::streambuf m_buffering; 64 | bool m_leave_output; 65 | string m_serial; 66 | 67 | // Numberic variables 68 | float m_f_max; 69 | int m_f_max_pos; 70 | int m_f_max_ind; 71 | int m_ind; 72 | int m_pos; 73 | 74 | int m_whole_distance; 75 | int m_steps; 76 | int m_min_steps; 77 | int m_number_images_sweep; 78 | int m_number_of_times; 79 | float m_precision; 80 | 81 | // Control strings for terminal commands 82 | string m_width; 83 | string m_height; 84 | string m_path; 85 | string m_name; 86 | 87 | string m_first_part_command; 88 | string m_first_part_name; 89 | string m_picture_input; 90 | string m_objective; 91 | 92 | // Image object 93 | CImg m_picture; 94 | 95 | // String commands... 96 | // ...without arguments 97 | string m_calibrate; 98 | string m_is_cal; 99 | string m_get_z_len; 100 | string m_get_z_pos; 101 | string m_get_z_distance; 102 | 103 | // ...with arguments 104 | string m_move_to; 105 | string m_move; 106 | string m_set_ring_colour; //takes a string as argument, not a number 107 | string m_set_ring_bright; //takes a number only between 0-255, 0 for off. Set to a default value otherwise 108 | string m_set_stage_led_bright; //takes a number only between 0-255, 0 for off. Set to a default value otherwise 109 | 110 | // Parts of commands accessible only from within the class... 111 | string m_number_steps; 112 | string m_number_pos; 113 | // ...indicating stopping controls 114 | string m_OK; 115 | string m_endpoint; 116 | 117 | 118 | // Private functions for class usage only 119 | // See function declaration for more details 120 | float algorithm(); 121 | 122 | void greyfy(); 123 | 124 | void raspistill_save(); 125 | 126 | void remove_picture(); 127 | void remove_folder(); 128 | 129 | float move_and_capture(int steps, int &f_pos); 130 | 131 | bool serial_command(string command, int &number, bool couting = false, string check = "OK\r"); 132 | bool serial_command(string command, string argument = "000000", bool couting = false, string check = "OK\r"); 133 | 134 | 135 | 136 | 137 | /* PUBLIC SECTION */ 138 | public: 139 | 140 | 141 | /* FUNCTION DECLARATION */ 142 | // Constructors and destructor 143 | Autofocus(); 144 | 145 | Autofocus(string serial_device, string objective_type, 146 | string path, string name, 147 | bool leave_output = true, 148 | string width = "480", string height = "360"); 149 | 150 | void initialise(); 151 | 152 | ~Autofocus(); 153 | 154 | 155 | 156 | // SET and GET functions 157 | // See details below for each functions working 158 | float get_max() 159 | { return m_f_max; } 160 | 161 | int get_max_pos() 162 | { return m_f_max_pos; } 163 | 164 | int get_max_index() 165 | { return m_f_max_ind; } 166 | 167 | int get_steps() 168 | { return m_steps; } 169 | 170 | void set_steps(int steps) 171 | { m_steps = steps; return; } 172 | 173 | void set_tolerance(float precision = 0.99) 174 | { m_precision = precision; return; } 175 | float get_tolerance() 176 | { return m_precision; } 177 | 178 | // Opens a serial port, by default on ttyUSB0. 179 | void set_serial(string s_port = "/dev/ttyUSB0") 180 | { m_serial = s_port; m_sp.open(s_port); sleep(3); return; } 181 | string get_serial() 182 | { return m_serial; } 183 | 184 | void set_width(string width = "480") 185 | { m_width = width; return; } 186 | string get_width() 187 | { return m_width; } 188 | 189 | void set_height(string height = "360") 190 | { m_height = height; return; } 191 | string get_height() 192 | { return m_height; } 193 | 194 | // Creates a directory and path where all output will be saved 195 | void set_path(string path = "./test/") 196 | { 197 | m_path = path; 198 | set_strings(); 199 | 200 | // Create directory where to work 201 | string making_directory = "mkdir " + path; 202 | system(making_directory.c_str()); 203 | return; 204 | } 205 | string get_path() 206 | { return m_path; } 207 | 208 | // Sets the common name for images 209 | void set_name(string name = "test") 210 | { 211 | m_name = name; 212 | set_strings(); 213 | return; 214 | } 215 | string get_name() 216 | { return m_name; } 217 | 218 | // Sets command strings for raspistill command to send to terminal and for saving images with correct path and name 219 | void set_strings() 220 | { 221 | m_first_part_command = "raspistill -n -w " + m_width + " -h " + m_height + " -o " + m_path + m_name; 222 | m_first_part_name = m_path + m_name; 223 | return; 224 | } 225 | 226 | // Sets a file where the values computed with the focusing formula are saved 227 | void set_file() 228 | { 229 | // Open output file for focusing values 230 | m_values.open((m_path + "focusingdata.txt").c_str()); 231 | return; 232 | } 233 | string get_file() 234 | { return m_path + "focusingdata.txt"; } 235 | 236 | // Sets whether the output should be deleted at the end or not (YES by default) 237 | void set_output(bool output = false) 238 | { m_leave_output = output; return; } 239 | bool get_output() 240 | { return m_leave_output; } 241 | 242 | // Sets minimum number of steps and initial number of steps depending on the objective chosen 243 | void set_objective(string objective_type = "4x") 244 | { 245 | m_objective = objective_type; 246 | // Set limiters for fine tuning 247 | if (objective_type.compare("4x") == 0) 248 | { 249 | m_min_steps = 5; 250 | m_steps = 560; 251 | } 252 | else if (objective_type.compare("10x") == 0) 253 | { 254 | m_min_steps = 2; 255 | m_steps = 100; 256 | } 257 | else if (objective_type.compare("40x") == 0) 258 | { 259 | m_min_steps = 1; 260 | m_steps = 20; 261 | } 262 | else if (objective_type.compare("100x") == 0) 263 | { 264 | m_min_steps = 1; 265 | m_steps = 5; 266 | } 267 | else 268 | { 269 | // Use default values. 270 | cout << "\nObjective not recognised, using default values." << endl; 271 | m_min_steps = 10; 272 | m_steps = 560; 273 | } 274 | return; 275 | } 276 | string get_objective() 277 | { return m_objective; } 278 | 279 | string get_calibrate() 280 | { return m_calibrate; } 281 | 282 | 283 | 284 | // Serial command functions. 285 | // These functions are for the user to send single commands to the Arduino separately from the inbuilt routines. 286 | bool comm_calibrate(bool out = false) 287 | { 288 | return serial_command(m_calibrate, "000000", out); 289 | } 290 | bool comm_is_calibrated(bool out = false) 291 | { 292 | return serial_command(m_is_cal, "000000", out); 293 | } 294 | bool comm_move(int steps, bool out = false) 295 | { 296 | return serial_command(m_move, steps, out); 297 | } 298 | bool comm_move_to(int position, bool out = false) 299 | { 300 | return serial_command(m_move_to, position, out); 301 | } 302 | bool comm_get_z_len(int &length, bool out = false) 303 | { 304 | return serial_command(m_get_z_len, length, out); 305 | } 306 | bool comm_get_z_pos(int &position, bool out = false) 307 | { 308 | return serial_command(m_get_z_pos, position, out); 309 | } 310 | bool comm_get_dist(bool out = false) 311 | { 312 | return serial_command(m_get_z_distance, "000000", out); 313 | } 314 | bool comm_set_ring_colour(string exa_value = "000000", bool out = false) 315 | { 316 | return serial_command(m_set_ring_colour, exa_value, out); 317 | } 318 | bool comm_set_ring_bright(int value, bool out = false) 319 | { 320 | return serial_command(m_set_ring_bright, value, out); 321 | } 322 | bool comm_set_led_bright(int value, bool out = false) 323 | { 324 | return serial_command(m_set_stage_led_bright, value, out); 325 | } 326 | 327 | 328 | // See function declarations for details 329 | bool fine_tune() 330 | { return fine_tune(m_f_max, m_f_max_pos); } 331 | bool fine_tune(float f_max, int f_max_pos, 332 | bool previous_direction = true, 333 | bool up_or_down = true, 334 | int times_checked = 0); 335 | 336 | void sweep(); 337 | 338 | void keep_in_focus(); 339 | 340 | void test_run(int); 341 | 342 | void stop_stage(string command = "not_calibrate\n", bool couting = false); 343 | 344 | }; 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | /* ########################################## 353 | * ##### METHODS DECLARATION ##### 354 | * ########################################## */ 355 | 356 | 357 | /* Autofocus class CONSTRUCTOR 358 | * Sets all variables to their values, either default or fixed 359 | * WARNING: this constructor will create a directory where to save all results automatically 360 | * Make sure that you have the right authorizations to do so when launching the program */ 361 | void Autofocus::initialise() 362 | { 363 | 364 | // Initialise Arduino commands 365 | m_calibrate = "calibrate\n"; 366 | m_is_cal = "is_calibrated\n"; 367 | m_get_z_len = "z_get_length\n"; 368 | m_get_z_pos = "z_get_position\n"; 369 | m_get_z_distance = "z_get_distance_to_go\n"; 370 | 371 | m_endpoint = "0\r"; 372 | m_OK = "OK\r"; 373 | 374 | m_move_to = "z_move_to"; 375 | m_move = "z_move"; 376 | m_set_ring_colour = "set_ring_colour"; 377 | m_set_ring_bright = "set_ring_brightness"; 378 | m_set_stage_led_bright = "set_stage_led_brightness"; 379 | 380 | // Initialise control variables 381 | m_f_max = 0; 382 | m_f_max_pos = 0; 383 | m_f_max_ind = 0; 384 | m_ind = 0; 385 | m_pos = 0; 386 | 387 | m_path = "./test/"; 388 | m_name = "test"; 389 | 390 | m_number_images_sweep = 10; 391 | m_number_of_times = 2; 392 | 393 | set_tolerance(); 394 | set_output(); 395 | set_objective(); 396 | 397 | set_width(); 398 | set_height(); 399 | //set_path(); 400 | //set_name(); 401 | //set_file(); 402 | 403 | // Create part of command and name strings 404 | set_strings(); 405 | 406 | //set_serial(); 407 | 408 | return; 409 | 410 | } 411 | 412 | // Allows user input for various parameters through the SET functions, 413 | // while using default values to start with 414 | Autofocus::Autofocus() 415 | :m_io(), m_sp(m_io) 416 | { 417 | 418 | initialise(); 419 | 420 | cout << "\nFinished initialising class." << endl; 421 | 422 | } 423 | 424 | // Takes parameters at constructor time and sets all variables accordingly 425 | Autofocus::Autofocus(string serial_device, string objective, 426 | string path, string name, 427 | bool leave_output, 428 | string width, string height) 429 | :m_io(), m_sp(m_io) 430 | { 431 | 432 | // Initialise Arduino commands 433 | initialise(); 434 | 435 | // Open serial port 436 | set_serial(serial_device); 437 | 438 | set_width(width); 439 | set_height(height); 440 | set_path(path); 441 | set_name(name); 442 | set_file(); 443 | 444 | // Create part of command and name strings 445 | set_strings(); 446 | 447 | set_output(leave_output); 448 | 449 | set_objective(objective); 450 | 451 | cout << "\nFinished initialising class" << endl; 452 | 453 | } 454 | 455 | /* Autofocus class DESTRUCTOR 456 | * Deletes the output folder if so required at the last operation executed by the program */ 457 | Autofocus::~Autofocus() 458 | { 459 | m_values.close(); 460 | 461 | if (!m_leave_output) 462 | remove_folder(); 463 | 464 | } 465 | 466 | 467 | 468 | 469 | //################################ 470 | /* Computes focusing algorithm 471 | * For a picture, it computes the focusing value */ 472 | float Autofocus::algorithm() 473 | { 474 | 475 | float intensity = 0.0; 476 | float mean_intensity = 0.0; 477 | float intensity_squared_sum = 0.0; 478 | float focusing = 0.0; 479 | 480 | greyfy(); 481 | 482 | // Calculate intensity of a matrix of pixels 483 | for (int x=0; x= m_f_max) 549 | { 550 | //Save position and value of maximum 551 | m_f_max = m_f_values[m_ind]; 552 | m_f_max_ind = m_ind; 553 | m_f_max_pos = pos; 554 | } 555 | m_ind++; 556 | 557 | // Remove picture if necessary 558 | if (!m_leave_output) 559 | remove_picture(); 560 | 561 | 562 | // Wait for the stage to finish moving 563 | stop_stage(); 564 | 565 | 566 | cout << "." << flush; 567 | 568 | 569 | // Exit after a certain number of images 570 | if (m_ind >= m_number_images_sweep) 571 | sweep_done = true; 572 | 573 | } 574 | 575 | cout << endl; 576 | 577 | return; 578 | 579 | } 580 | 581 | 582 | 583 | 584 | //################################################# 585 | /* Makes fine corrections to the focusing point by checking above and below the starting point. 586 | * It can be used separately or in conjunction with the sweep function to do a complete autofocusing. */ 587 | bool Autofocus::fine_tune(float f_max, int f_max_pos, 588 | bool previous_direction, 589 | bool up_or_down, 590 | int times_checked) 591 | { 592 | 593 | float f_above = 0; 594 | float f_below = 0; 595 | int f_above_pos = 0; 596 | int f_below_pos = 0; 597 | 598 | 599 | if (!previous_direction && m_steps > m_min_steps) 600 | { 601 | //cout << "\nReducing number of steps... " << endl; 602 | m_steps = (int)(0.5*m_steps); 603 | } 604 | else if (m_steps <= m_min_steps) 605 | { 606 | //cout << "\nUsing minimum number of steps: " << m_min_steps << endl; 607 | m_steps = m_min_steps; 608 | } 609 | 610 | 611 | // Take picture at starting point 612 | raspistill_save(); 613 | 614 | 615 | // Compute MIDDLE picture 616 | f_max = move_and_capture(0, f_max_pos); 617 | cout << "." << flush; 618 | m_values << m_ind << "\t" << f_max << endl; 619 | m_ind++; 620 | 621 | // Set max values for future use 622 | m_f_max = f_max; 623 | m_f_max_pos = f_max_pos; 624 | 625 | // Remove picture if necessary 626 | if (!m_leave_output) 627 | remove_picture(); 628 | 629 | 630 | //cout << "\nStart call at\n" << f_max_pos << "\t" << f_max << endl; 631 | 632 | 633 | 634 | if (up_or_down) 635 | // Start checking from ABOVE the starting position 636 | { 637 | 638 | //cout << "\nChecking UP..." << endl; 639 | 640 | f_above = move_and_capture(m_steps, f_above_pos); 641 | //cout << f_above_pos << "\t" << f_above << endl; 642 | cout << "." << flush; 643 | 644 | // Remove picture if necessary 645 | if (!m_leave_output) 646 | remove_picture(); 647 | 648 | 649 | 650 | if (f_above >= ((2.0-m_precision)*f_max)) 651 | { 652 | 653 | //cout << "\nStaying UP..." << endl; 654 | 655 | // Keep checking up, maintaining the same number of steps 656 | fine_tune(f_above, f_above_pos, true, true); 657 | 658 | } 659 | else 660 | { 661 | 662 | //cout << "\nChecking DOWN..." << endl; 663 | 664 | f_below = move_and_capture(-2*m_steps, f_below_pos); 665 | //cout << f_below_pos << "\t" << f_below << endl; 666 | cout << "." << flush; 667 | 668 | // Remove picture if necessary 669 | if (!m_leave_output) 670 | remove_picture(); 671 | 672 | 673 | 674 | if (f_below >= ((2.0-m_precision)*f_max)) 675 | { 676 | 677 | //cout << "\nStaying DOWN..." << endl; 678 | 679 | // Change direction of movement and continue checking down 680 | fine_tune(f_below, f_below_pos, false, false); 681 | 682 | } 683 | else 684 | { 685 | 686 | //cout << "\nI was already there, so I am going back... " << times_checked << endl; 687 | 688 | // Move back to maximum 689 | serial_command(m_move_to, f_max_pos); 690 | stop_stage(); 691 | 692 | // If the maximum hasn't changed lately (in the last two checks) then we have arrived... 693 | if (times_checked == m_number_of_times && m_steps > m_min_steps) 694 | { 695 | m_steps = m_min_steps; 696 | fine_tune(f_max, f_max_pos, false, false, ++times_checked); 697 | } 698 | else if (times_checked < m_number_of_times && m_steps > m_min_steps) 699 | { 700 | fine_tune(f_max, f_max_pos, false, false, ++times_checked); 701 | } 702 | else 703 | { 704 | return true; 705 | } 706 | 707 | } 708 | 709 | } 710 | 711 | } 712 | 713 | 714 | 715 | else 716 | // Start checking from BELOW the starting position 717 | { 718 | 719 | //cout << "\nChecking DOWN..." << endl; 720 | 721 | f_below = move_and_capture(-m_steps, f_below_pos); 722 | //cout << f_below_pos << "\t" << f_below << endl; 723 | cout << "." << flush; 724 | 725 | // Remove picture if necessary 726 | if (!m_leave_output) 727 | remove_picture(); 728 | 729 | 730 | if (f_below > ((2.0-m_precision)*f_max)) 731 | { 732 | 733 | //cout << "\nStaying DOWN..." << endl; 734 | 735 | // Keep checking down, maintaining the same number of steps 736 | fine_tune(f_below, f_below_pos, true, false); 737 | 738 | } 739 | else 740 | { 741 | 742 | //cout << "\nChecking UP..." << endl; 743 | 744 | f_above = move_and_capture(2*m_steps, f_above_pos); 745 | //cout << f_above_pos << "\t" << f_above << endl; 746 | cout << "." << flush; 747 | 748 | // Remove picture if necessary 749 | if (!m_leave_output) 750 | remove_picture(); 751 | 752 | 753 | if (f_above > ((2.0-m_precision)*f_max)) 754 | { 755 | 756 | //cout << "\nStaying UP..." << endl; 757 | 758 | // Invert direction and start checking above 759 | fine_tune(f_above, f_above_pos, false, true); 760 | 761 | } 762 | else 763 | { 764 | 765 | //cout << "\nI was already there, so I am going back... " << times_checked << endl; 766 | 767 | // Move back to maximum 768 | serial_command(m_move_to, f_max_pos); 769 | stop_stage(); 770 | 771 | // If the maximum hasn't changed lately (in the last two checks) then we have arrived... 772 | if (times_checked == m_number_of_times && m_steps > m_min_steps) 773 | { 774 | m_steps = m_min_steps; 775 | fine_tune(f_max, f_max_pos, false, true, ++times_checked); 776 | } 777 | else if (times_checked < m_number_of_times && m_steps > m_min_steps) 778 | { 779 | fine_tune(f_max, f_max_pos, false, true, ++times_checked); 780 | } 781 | else 782 | { 783 | return true; 784 | } 785 | 786 | } 787 | 788 | } 789 | 790 | } 791 | 792 | return true; 793 | 794 | } 795 | 796 | 797 | 798 | 799 | //################################## 800 | /* Keeps microscope in focus, and readjusts if things are changed. 801 | * To be used after fine_tune has completed, since it assumes the starting point is almost in focus already. */ 802 | void Autofocus::keep_in_focus() 803 | { 804 | 805 | bool stay_in_focus = true; 806 | while (stay_in_focus == true) 807 | { 808 | sleep(120); 809 | 810 | m_steps = 40; 811 | 812 | fine_tune(); 813 | } 814 | 815 | return; 816 | 817 | } 818 | 819 | 820 | 821 | 822 | //############################################## 823 | /* Executes a test run. 824 | * This corresponds to a predetermined number of images and step separation, taken at equal distances and with values saved in the previously mentioned file. */ 825 | void Autofocus::test_run(int number_images) 826 | { 827 | 828 | serial_command(m_get_z_len, m_whole_distance); 829 | cout << "\nLength of travel: " << m_whole_distance << endl; 830 | 831 | 832 | // Establish how many steps between each image, and assign to the command move 833 | int number_steps = (int)-m_whole_distance/number_images; 834 | cout << "\nImages to be taken: " << number_images; 835 | cout << "\nDistance between images: " << number_steps << endl; 836 | 837 | 838 | cout << "\nExecuting test run" << flush; 839 | m_ind = 0; 840 | while (m_ind < number_images) 841 | { 842 | 843 | // Create string for raspistill command and for name of image 844 | raspistill_save(); 845 | //cout << m_picture_input << endl; 846 | 847 | 848 | // Create picture to analise 849 | m_picture.assign(m_picture_input.c_str()); 850 | 851 | 852 | // Move the stage to next picture position 853 | serial_command(m_move, number_steps); 854 | 855 | 856 | // Calculate focusing value for the latest picture 857 | m_f_values.push_back( algorithm() ); 858 | m_values << m_ind << "\t" << m_f_values[m_ind] << endl; 859 | m_ind++; 860 | 861 | 862 | // Remove picture if necessary 863 | if (!m_leave_output) 864 | remove_picture(); 865 | 866 | 867 | // Wait for stage to finish moving 868 | stop_stage(); 869 | 870 | cout << "." << flush; 871 | 872 | } 873 | 874 | string save_the_data = "mv " + m_path + "focusingdata.txt ../"; 875 | system(save_the_data.c_str()); 876 | 877 | cout << endl; 878 | 879 | return; 880 | 881 | } 882 | 883 | 884 | 885 | 886 | //################################################ 887 | /* Turns image to greyscale. */ 888 | void Autofocus::greyfy() 889 | { 890 | 891 | for (int x=0; x((int)(number)); 1211 | ss << command << " " << number_in_words << "\n"; 1212 | write(m_sp, buffer(ss.str())); 1213 | ss.str(""); 1214 | 1215 | while (exiting == false) 1216 | { 1217 | boost::asio::read_until(m_sp, m_buffering, '\n'); 1218 | getline(is, line); 1219 | if (couting) 1220 | cout << line << endl; 1221 | if (line.compare(check) == 0) 1222 | { 1223 | exiting = true; 1224 | control = true; 1225 | } 1226 | 1227 | if (line.compare("ERR: UNKNOWN COMMAND\r") == 0) 1228 | { 1229 | exiting = true; 1230 | } 1231 | if (line.compare("ERR: NOT CALIBRATED\r") == 0) 1232 | { 1233 | exiting = true; 1234 | } 1235 | if (line.compare("ERR: POSITION OUT OF RANGE\r") == 0) 1236 | { 1237 | exiting = true; 1238 | } 1239 | 1240 | line.clear(); 1241 | } 1242 | } 1243 | // Requires signed integer as argument 1244 | else if (command.compare(m_move) == 0) 1245 | { 1246 | string number_in_words = boost::lexical_cast((int)(number)); 1247 | ss << command << " " << number_in_words << "\n"; 1248 | write(m_sp, buffer(ss.str())); 1249 | ss.str(""); 1250 | 1251 | while (exiting == false) 1252 | { 1253 | boost::asio::read_until(m_sp, m_buffering, '\n'); 1254 | getline(is, line); 1255 | if (couting) 1256 | cout << line << endl; 1257 | if (line.compare(check) == 0) 1258 | { 1259 | exiting = true; 1260 | control = true; 1261 | } 1262 | 1263 | if (line.compare("ERR: UNKNOWN COMMAND\r") == 0) 1264 | { 1265 | exiting = true; 1266 | } 1267 | if (line.compare("ERR: NOT CALIBRATED\r") == 0) 1268 | { 1269 | exiting = true; 1270 | } 1271 | if (line.compare("ERR: POSITION OUT OF RANGE\r") == 0) 1272 | { 1273 | exiting = true; 1274 | } 1275 | 1276 | line.clear(); 1277 | } 1278 | } 1279 | // Requires a number between 0 and 255 as argument 1280 | else if (command.compare(m_set_stage_led_bright) == 0 || command.compare(m_set_ring_bright) == 0) 1281 | { 1282 | if (number < 0 || number > 255) 1283 | number = 70; 1284 | 1285 | string number_in_words = boost::lexical_cast((int)(number)); 1286 | ss << command << " " << number_in_words << "\n"; 1287 | write(m_sp, buffer(ss.str())); 1288 | ss.str(""); 1289 | 1290 | while (exiting == false) 1291 | { 1292 | boost::asio::read_until(m_sp, m_buffering, '\n'); 1293 | getline(is, line); 1294 | if (couting) 1295 | cout << line << endl; 1296 | if (line.compare(check) == 0) 1297 | { 1298 | exiting = true; 1299 | control = true; 1300 | } 1301 | 1302 | if (line.compare("ERR: UNKNOWN COMMAND\r") == 0) 1303 | { 1304 | exiting = true; 1305 | } 1306 | if (line.compare("ERR: NOT CALIBRATED\r") == 0) 1307 | { 1308 | exiting = true; 1309 | } 1310 | if (line.compare("ERR: POSITION OUT OF RANGE\r") == 0) 1311 | { 1312 | exiting = true; 1313 | } 1314 | 1315 | line.clear(); 1316 | } 1317 | } 1318 | else 1319 | { 1320 | ss << command; 1321 | write(m_sp, buffer(ss.str())); 1322 | ss.str(""); 1323 | 1324 | while (exiting == false) 1325 | { 1326 | boost::asio::read_until(m_sp, m_buffering, '\n'); 1327 | getline(is, line); 1328 | if (couting) 1329 | cout << line << endl; 1330 | if (atoi(line.c_str()) != 0) 1331 | number = atoi(line.c_str()); 1332 | if (line.compare(check) == 0) 1333 | { 1334 | exiting = true; 1335 | control = true; 1336 | } 1337 | 1338 | if (line.compare("ERR: UNKNOWN COMMAND\r") == 0) 1339 | { 1340 | exiting = true; 1341 | } 1342 | if (line.compare("ERR: NOT CALIBRATED\r") == 0) 1343 | { 1344 | exiting = true; 1345 | } 1346 | if (line.compare("ERR: POSITION OUT OF RANGE\r") == 0) 1347 | { 1348 | exiting = true; 1349 | } 1350 | 1351 | line.clear(); 1352 | } 1353 | } 1354 | 1355 | return control; 1356 | } 1357 | 1358 | 1359 | #endif 1360 | -------------------------------------------------------------------------------- /Raspberry Pi/CPP/autofocus_class_initialisation.h: -------------------------------------------------------------------------------- 1 | // Autofocus Class Initialisation 2 | 3 | /* Provides user interface to initialise the Autofocus class. 4 | * the autofocus_initialisation(Autofocus&) method should be used to set up the class the first time. 5 | * autofocus_reset(Autofocus&) can be used to change parameters while the program is running. 6 | */ 7 | 8 | #ifndef AUTOFOCUS_CLASS_INITIALISATION_H 9 | #define AUTOFOCUS_CLASS_INITIALISATION_H 10 | 11 | #include "autofocus_class.h" 12 | 13 | void autofocus_initialisation(Autofocus&); 14 | void autofocus_reset(Autofocus&); 15 | 16 | 17 | // Initialising parameters in class autodoing 18 | // To be used to change the default parameters normally used at class initialisation 19 | // Remember to open serial port, as standard constructor of class does not do so 20 | void autofocus_initialisation(Autofocus &autodoing) 21 | { 22 | 23 | autodoing.set_width(); 24 | autodoing.set_height(); 25 | 26 | // ## CONSTRUCTOR VARIABLES SELECTION 27 | 28 | // Type in serial port to connect Arduino 29 | string port; 30 | cout << "\n\tOn what port is the arduino (default)?\n\t" << flush; cin >> port; 31 | if (port.compare("default") == 0) 32 | port = "/dev/ttyUSB0"; 33 | else if (port[0] == 't') 34 | port = "/dev/" + port; 35 | else 36 | port = "/dev/tty" + port; 37 | 38 | autodoing.set_serial(port); 39 | 40 | 41 | // Objective picking 42 | string objective; 43 | cout << "\n\tWhat kind of objective will we be using (4x, 10x or 40x)?\n\t" << flush; cin >> objective; 44 | 45 | autodoing.set_objective(objective); 46 | 47 | 48 | // Choose whether to maintain output or not, and create variables for it 49 | char output_yes_no; 50 | bool keep_output = true; 51 | string read_path; 52 | string read_name; 53 | cout << "\n\tWould you like to keep the output (y/n)? "; cin >> output_yes_no; 54 | if (output_yes_no == 'n') 55 | { 56 | keep_output = false; 57 | read_path = "./.temporary/"; 58 | read_name = "temporary"; 59 | } 60 | else 61 | { 62 | // Choose path for output 63 | cout << "\n\tType where images will be stored (full path or just name of folder):\n\t" << flush; cin >> read_path; 64 | if (read_path[0] != '/') 65 | read_path.insert(0, "./"); 66 | if (read_path[read_path.length()-1] != '/') 67 | read_path.push_back('/'); 68 | 69 | // Choose common name for images to be saved 70 | cout << "\n\tType common name of images:\n\t" << flush; cin >> read_name; 71 | } 72 | 73 | autodoing.set_output(keep_output); 74 | autodoing.set_path(read_path); 75 | autodoing.set_name(read_name); 76 | autodoing.set_file(); 77 | autodoing.set_strings(); 78 | 79 | 80 | // Set brightness of backlight LED 81 | int brightness = 0; 82 | cout << "\n\tChoose brightness of LED for backlight (0-255, 0 for off, -1 for default):\n\t" << flush; cin >> brightness; 83 | if (brightness < 0 || brightness > 255) 84 | { 85 | brightness = 70; 86 | cout << "\nUsing default value, " << brightness << endl; 87 | } 88 | 89 | autodoing.comm_set_led_bright(brightness); 90 | 91 | 92 | // Set tolerance of working 93 | float tolerance; 94 | cout << "\n\tChoose tolerance of comparison between values (0->1):\n\t" << flush; cin >> tolerance; 95 | if (tolerance < 0 || tolerance > 1) 96 | { 97 | tolerance = 0.98; 98 | cout << "\nUsing default value, " << tolerance << endl; 99 | } 100 | 101 | autodoing.set_tolerance(tolerance); 102 | 103 | // ## END OF CONSTRUCTOR VARIABLES SELECTION 104 | 105 | return; 106 | 107 | } 108 | 109 | 110 | 111 | // Resetting parameters for new call of the program 112 | void autofocus_reset(Autofocus &autodoing) 113 | { 114 | 115 | char change; 116 | 117 | // Change objective 118 | cout << "\n\tDo you wish to change objective (y/n)? "; cin >> change; 119 | if (change == 'y') 120 | { 121 | string obj; 122 | cout << "\n\tWhat kind of objective will we be using (4x, 10x or 40x)?\n\t" << flush; cin >> obj; 123 | autodoing.set_objective(obj); 124 | } 125 | 126 | 127 | // Change path of next operation 128 | bool keep_output = true; 129 | string read_path; 130 | string read_name; 131 | cout << "\n\tDo you wish to keep the output for the next operation (y/n)? "; cin >> change; 132 | if (change == 'n') 133 | { 134 | keep_output = false; 135 | read_path = "./.temporary/"; 136 | read_name = "temporary"; 137 | } 138 | else 139 | { 140 | // Choose path for output 141 | cout << "\n\tType where images will be stored (full path or just name of folder):\n\t" << flush; cin >> read_path; 142 | if (read_path[0] != '/') 143 | read_path.insert(0, "./"); 144 | if (read_path[read_path.length()-1] != '/') 145 | read_path.push_back('/'); 146 | 147 | // Choose common name for images to be saved 148 | cout << "\n\tType common name of images:\n\t" << flush; cin >> read_name; 149 | } 150 | autodoing.set_output(keep_output); 151 | autodoing.set_path(read_path); 152 | autodoing.set_name(read_name); 153 | autodoing.set_strings(); 154 | 155 | 156 | // Set brightness of LED 157 | int brightness = 0; 158 | cout << "\n\tChoose brightness of LED for backlight (0-255, 0 for off, -1 for default):\n\t" << flush; cin >> brightness; 159 | if (brightness < 0 || brightness > 255) 160 | { 161 | brightness = 70; 162 | cout << "\nUsing default value, " << brightness << endl; 163 | } 164 | autodoing.comm_set_led_bright(brightness); 165 | 166 | 167 | // Set tolerance of working 168 | float tolerance; 169 | cout << "\n\tChoose tolerance of comparison between values (0->1):\n\t" << flush; cin >> tolerance; 170 | if (tolerance < 0 || tolerance > 1) 171 | { 172 | tolerance = 0.98; 173 | cout << "\nUsing default value, " << tolerance << endl; 174 | } 175 | autodoing.set_tolerance(tolerance); 176 | 177 | return; 178 | 179 | } 180 | 181 | #endif 182 | -------------------------------------------------------------------------------- /Raspberry Pi/CPP/edgedetection_class.h: -------------------------------------------------------------------------------- 1 | // Edge Detection Class 2 | 3 | /* This file contains the class that contains all variables and methods necessary to implement the Canny edge detection algorithm. 4 | * These are: 5 | * 6 | * public: 7 | * Edgedetection(string) -> Only class constructor. 8 | * Uses string as location of the file to be opened. 9 | * Full path should be provided, and it's the main program's job to make sure that the full path is passed to the constructor. 10 | * ~Edgedetection() -> Class destructor. 11 | * Deallocates all memory allocated dinamically during the construction and execution of methods in the class. 12 | * canny_edge_detection() -> Executes the algorithm of edge detection on the image at the path used in the constructor. 13 | * It will display all changes made on the image by the subsequent methods. 14 | * 15 | * private: 16 | * greyfy() -> Turns an image into greyscale. 17 | * CAUTION! Because of the way this is implemented, this program will work only on images that are NOT previously in greyscale. 18 | * load_matrix() -> Loads a noise-damping convolution matrix from file. 19 | * Read comments on methods to see all details on how this is done. 20 | * picture_convolution() -> Convolves the image with the previously loaded matrix to dampen the effect of artifacts on the end result. 21 | * simple_gradient() -> Computes the gradient associated with each pixel using a simple method. 22 | * The choice of this method or the next is totally arbitrary. 23 | * They are both provided just as different options. 24 | * sobel_gradient() -> Computes the gradient associated with each pixel using the Sobel algorithm. 25 | * This is a more complex method than the previous one, and it is supposed to be more precise. 26 | * Whether this is true or not can be tested by the user at his/her leisure. 27 | * By default, however, this is the gradient algorithm preferred. 28 | * edge_decision(float, float) -> This method takes a high and low threshold as a multiplier of the average modulus of the gradients of the picture. 29 | * It will then divide the pixels in three cathegories depending on the modulus of their gradient: 30 | * above high threshold -> true edge 31 | * between high and low threshold -> secondary edge 32 | * below low threshold -> not an edge 33 | * edge_selection() -> This method decides whether secondary edges are true edges or not depending on various criteria, mostly dependent on their proximity to a true edge. 34 | * crop_and_save() -> Removes the border of the image, necessarely turned black by the previous method (read descriptions) and saves the result image to file. 35 | */ 36 | 37 | 38 | 39 | #ifndef EDGEDETECTION_CLASS_H 40 | #define EDGEDETECTION_CLASS_H 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | #include "CImg.h" 53 | 54 | #define PI 3.14159265359 55 | 56 | using namespace cimg_library; 57 | using namespace std; 58 | using namespace boost::asio; 59 | 60 | 61 | class Edgedetection 62 | { 63 | 64 | private: 65 | 66 | CImg m_picture; 67 | CImgDisplay m_show; 68 | 69 | float ** m_matrix; 70 | float *** m_gradient; 71 | int ** m_edge; 72 | int m_size_matrix; 73 | 74 | char m_input_multipliers; 75 | char m_save; 76 | 77 | 78 | void edge_decision(float high_thr_mult = 3, float low_thr_mult = 1.2); 79 | 80 | void edge_selection(); 81 | 82 | void simple_gradient(); 83 | 84 | void sobel_gradient(); 85 | 86 | void picture_convolution(); 87 | 88 | float sum_matrix(float **, int, int); 89 | 90 | void crop_and_save(); 91 | 92 | void greyfy(); 93 | 94 | void load_matrix(); 95 | 96 | 97 | public: 98 | 99 | Edgedetection(string); 100 | 101 | ~Edgedetection(); 102 | 103 | CImg canny_edge_detection(); 104 | 105 | 106 | }; 107 | 108 | 109 | 110 | 111 | /* Edgedetection class CONSTRUCTOR 112 | * It contains all interface necessary for the correct execution of the algorithm 113 | * Note that the matrix size for noise damping is pre-established here, so the matrix loaded in canny_edge_detection() method must be of same size! 114 | * We provide one such matrix in a file available in the 'Edge Detection' folder 115 | * Make sure the matrix is in the same folder as the executable file at runtime */ 116 | Edgedetection::Edgedetection(string picture_location) 117 | { 118 | 119 | m_picture.assign(picture_location.c_str()); 120 | 121 | m_size_matrix = 5; 122 | 123 | cout << "\nDo you wish to save the image after processing (y/n)? "; 124 | cin >> m_save; 125 | 126 | cout << "\nWould you like to input your own factors (y/n)? "; 127 | cout << "\nNOTE: If 'n' is selected, default ones will be used... "; 128 | cin >> m_input_multipliers; 129 | 130 | // Create 3D matrix of gradient values 131 | m_gradient = new float**[m_picture.width()]; 132 | for (int x=0; x Edgedetection::canny_edge_detection() 195 | { 196 | 197 | // First we show the picture we start with 198 | m_show.display(m_picture); 199 | 200 | 201 | // Load convolution matrix for noise damping 202 | // This matrix will be convolved with the image to smooth away artifacts and 'ruined' pixels 203 | load_matrix(); 204 | cout << "\nFinished loading convolution matrix for noise filtering" << endl; 205 | 206 | 207 | 208 | // Reduce image to greyscale (intensity scale) 209 | // This is necessary for the following analysis, since we are interested in the intensity of the pixels and not their colour 210 | //if ((m_picture(0,0,0,0) != m_picture(0,0,0,1)) || (m_picture(0,0,0,0) != m_picture(0,0,0,2))) 211 | //{ 212 | greyfy(); 213 | cout << "\nFinished turning image to greyscale" << endl; 214 | //} 215 | //else 216 | // cout << "\nImage is already in greyscale" << endl; 217 | 218 | // Display the image after turning to grayscale 219 | m_show.display(m_picture); 220 | 221 | 222 | 223 | // Apply convolution with preset matrix 224 | picture_convolution(); 225 | 226 | m_show.display(m_picture); 227 | 228 | cout << "\nFinished noise filtering" << endl; 229 | 230 | 231 | 232 | // Calculate gradients associated with each pixel 233 | // Refer to the 'Canny Edge Detector' article on Wikipedia to know why this is necessary 234 | // Here we have implemented two possibilities for the gradient calculation 235 | // See the specific methods within the class for further details 236 | //simple_gradient(); 237 | sobel_gradient(); 238 | 239 | cout << "\nFinished calculating gradient for the pixels" << endl; 240 | 241 | 242 | 243 | // Decide whether each pixel is on the edge or not 244 | // This is done following the Canny Edge Detection method of minor and major edges 245 | // See method for details 246 | edge_decision(); 247 | 248 | // Assign different grey tonalities to major edges, minor edges and non-edges respectively 249 | for (int i=0; i> high_thr_mult; 360 | cout << "\tInsert low threshold multiplier : "; 361 | cin >> low_thr_mult; 362 | m_show.show(); 363 | } 364 | float high_thr = average * high_thr_mult; 365 | float low_thr = average * low_thr_mult; 366 | 367 | // Establish primary and secondary edges 368 | for (int i=0; i high_thr) 379 | m_edge[i][j] = 2; 380 | else if (m_gradient[i][j][2] > low_thr) 381 | m_edge[i][j] = 1; 382 | else 383 | m_edge[i][j] = 0; 384 | } 385 | else if (m_gradient[i][j][3] == 45 && m_gradient[i+1][j+1][2] < m_gradient[i][j][2] && m_gradient[i-1][j-1][2] < m_gradient[i][j][2]) 386 | { 387 | if (m_gradient[i][j][2] > high_thr) 388 | m_edge[i][j] = 2; 389 | else if (m_gradient[i][j][2] > low_thr) 390 | m_edge[i][j] = 1; 391 | else 392 | m_edge[i][j] = 0; 393 | } 394 | else if (m_gradient[i][j][3] == 90 && m_gradient[i][j-1][2] < m_gradient[i][j][2] && m_gradient[i][j+1][2] < m_gradient[i][j][2]) 395 | { 396 | if (m_gradient[i][j][2] > high_thr) 397 | m_edge[i][j] = 2; 398 | else if (m_gradient[i][j][2] > low_thr) 399 | m_edge[i][j] = 1; 400 | else 401 | m_edge[i][j] = 0; 402 | } 403 | else if (m_gradient[i][j][3] == 135 && m_gradient[i-1][j+1][2] < m_gradient[i][j][2] && m_gradient[i+1][j-1][2] < m_gradient[i][j][2]) 404 | { 405 | if (m_gradient[i][j][2] > high_thr) 406 | m_edge[i][j] = 2; 407 | else if (m_gradient[i][j][2] > low_thr) 408 | m_edge[i][j] = 1; 409 | else 410 | m_edge[i][j] = 0; 411 | } 412 | else 413 | m_edge[i][j] = 0; 414 | 415 | } 416 | } 417 | 418 | return; 419 | 420 | } 421 | 422 | 423 | 424 | 425 | /* Establish whether minor edges should be part of major or not 426 | * The picture is swept first left to right to check whether minor edges are continuation or close neighbours of major edges 427 | * Then the picture is swept right to left to make sure that nothing is left unchecked (edges can go in both directions!) 428 | * This is necessary because if a minor edge connects to a major edge at its rightmost point, it will be ignored in the first sweep but not in the second */ 429 | void Edgedetection::edge_selection() 430 | { 431 | 432 | // Swipe through secondary edges first time to assign them to primary or not 433 | for (int i=2; i2; i--) { 453 | for (int j=m_picture.height()-2; j>2; j--) 454 | { 455 | 456 | if (m_edge[i][j] == 1) 457 | { 458 | for (int x=-2; x<3; x++) { 459 | for (int y=-2; y<3; y++) 460 | { 461 | if (m_edge[i-x][j-y] == 2) 462 | m_edge[i][j] = 2; 463 | } 464 | } 465 | } 466 | 467 | } 468 | } 469 | 470 | // Cleanup 471 | for (int i=0; i= 7.0*PI/8.0) m_gradient[i][j][3] = 0; 515 | else if (PI/8.0 <= temporary && temporary < 3.0*PI/8.0) m_gradient[i][j][3] = 45; 516 | else if (3.0*PI/8.0 <= temporary && temporary < 5.0*PI/8.0) m_gradient[i][j][3] = 90; 517 | else if (5.0*PI/8.0 <= temporary && temporary < 7.0*PI/8.0) m_gradient[i][j][3] = 135; 518 | else m_gradient[i][j][3] = 0; 519 | } 520 | 521 | //cout << m_gradient[i][j][0] << " " << m_gradient[i][j][1] << " " << m_gradient[i][j][2]; 522 | 523 | } 524 | 525 | //cout << endl; 526 | } 527 | 528 | return; 529 | 530 | } 531 | 532 | 533 | 534 | 535 | /* Compute the gradient of pixels in an image using the Sobel algorithm 536 | * See Wikipedia article on Sobel gradient for edge detection for details 537 | * Note that gradients also have a direction, which at the end of this method is simplified into four possible angles since pixels can only change horizontally, vertically or diagonally */ 538 | void Edgedetection::sobel_gradient() 539 | { 540 | 541 | float temporary; 542 | 543 | for (int i=0; i= 7.0*PI/8.0) m_gradient[i][j][3] = 0; 566 | else if (PI/8.0 <= temporary && temporary < 3.0*PI/8.0) m_gradient[i][j][3] = 45; 567 | else if (3.0*PI/8.0 <= temporary && temporary < 5.0*PI/8.0) m_gradient[i][j][3] = 90; 568 | else if (5.0*PI/8.0 <= temporary && temporary < 7.0*PI/8.0) m_gradient[i][j][3] = 135; 569 | else m_gradient[i][j][3] = 0; 570 | 571 | } 572 | //cout << endl; 573 | } 574 | 575 | return; 576 | 577 | } 578 | 579 | 580 | 581 | 582 | /* Convolves an image with the matrix given 583 | * WARNING! It will assume that the size of the side of the matrix loaded is of ODD length 584 | * Otherwise, it goes boom 585 | * If you don't know what matrix convolution in terms of computational mathematics is, well, Google it */ 586 | void Edgedetection::picture_convolution() 587 | { 588 | 589 | CImg convolution(m_picture.width(),m_picture.height(),1,3); 590 | int limit = (m_size_matrix - 1)/2; 591 | float ** temp = new float * [m_size_matrix]; 592 | for (int x=0; x> factor; 688 | for (int i=0; i> element; 692 | m_matrix[i][j] = factor * element; 693 | } 694 | } 695 | 696 | reading.close(); 697 | 698 | return; 699 | 700 | } 701 | 702 | 703 | 704 | /* Crop and save image, removing black edges 705 | * In the edge_selection method we created a black rim around the images because some pixels don't have neighbours to calculate the gradient from 706 | * Now, since it looks bad, we remove it */ 707 | void Edgedetection::crop_and_save() 708 | { 709 | 710 | CImg cropped(m_picture.width()-6, m_picture.height()-6, 1, 3); 711 | 712 | for (int x=0; x> name; 25 | if (name[0] == '/') 26 | { 27 | ss.str(""); 28 | ss << name << ".jpg"; 29 | } 30 | else 31 | { 32 | ss << name << ".jpg"; 33 | } 34 | 35 | string extension = ss.str(); 36 | const char * path = extension.c_str(); 37 | cout << "\nOpening " << path << endl; 38 | 39 | Edgedetection detecting(path); 40 | 41 | detecting.canny_edge_detection(); 42 | 43 | return 0; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Raspberry Pi/CPP/focus_everything.cpp: -------------------------------------------------------------------------------- 1 | // Focusing Main Program 2 | 3 | /* Provides controls for the functionalities of the microscope, and a basic user interface through terminal. 4 | */ 5 | 6 | #include "autofocus_class.h" 7 | #include "autofocus_class_initialisation.h" 8 | #include "focus_everything.h" 9 | 10 | 11 | int main () 12 | { 13 | 14 | Autofocus autofocusing; 15 | 16 | char defaults; 17 | cout << "\nDo you wish to input your own parameters (y/n)? "; cin >> defaults; 18 | if (defaults == 'y') 19 | autofocus_initialisation(autofocusing); 20 | else if (defaults == 'n') 21 | { 22 | cout << "\nUsing default parameters..." << endl; 23 | autofocusing.set_serial(); 24 | cout << "Serial port: " << autofocusing.get_serial() << endl; 25 | cout << "Objective: " << autofocusing.get_objective() << endl; 26 | cout << "Keeping output: " << autofocusing.get_output() << endl; 27 | autofocusing.set_path(); 28 | cout << "Destination folder: " << autofocusing.get_path() << endl; 29 | autofocusing.set_file(); 30 | cout << "File for data saving: " << autofocusing.get_file() << endl; 31 | autofocusing.set_name(); 32 | cout << "Common picture name: " << autofocusing.get_name() << endl; 33 | autofocusing.comm_set_led_bright(70); 34 | cout << "Backlight LED brightness (0->255): " << 70 << endl; 35 | cout << "Tolerance (0->1): " << autofocusing.get_tolerance() << endl; 36 | } 37 | else 38 | { 39 | cout << "\nNOT RECOGNISED! Using default parameters..." << endl; 40 | autofocusing.set_serial(); 41 | cout << "Serial port: " << autofocusing.get_serial() << endl; 42 | cout << "Objective: " << autofocusing.get_objective() << endl; 43 | cout << "Keeping output: " << autofocusing.get_output() << endl; 44 | autofocusing.set_path(); 45 | cout << "Destination folder: " << autofocusing.get_path() << endl; 46 | autofocusing.set_file(); 47 | cout << "File for data saving: " << autofocusing.get_file() << endl; 48 | autofocusing.set_name(); 49 | cout << "Common picture name: " << autofocusing.get_name() << endl; 50 | autofocusing.comm_set_led_bright(70); 51 | cout << "Backlight LED brightness (0->255): " << 70 << endl; 52 | cout << "Tolerance (0->1): " << autofocusing.get_tolerance() << endl; 53 | } 54 | 55 | 56 | cout << "\nWARNING: Remember to calibrate at the start of the program!" << flush; 57 | 58 | bool keep_working = true; 59 | int times_cycled = 0; 60 | while (keep_working) 61 | { 62 | 63 | string program_choice; 64 | cout << "\n\tWhat program would you like to run ('full', 'sweep', 'tune', 'test', 'calibrate', 'serial', 'exit')?\n\t" << flush; cin >> program_choice; 65 | 66 | if (times_cycled > 1 && program_choice.compare("exit") != 0 && program_choice.compare("serial") != 0) 67 | { 68 | char reset_choice; 69 | cout << "\n\tDo you wish to change some parameters for the next execution (y/n)? "; cin >> reset_choice; 70 | if (reset_choice == 'y') 71 | autofocus_reset(autofocusing); 72 | else if (reset_choice == 'n') 73 | cout << "\nContinuing with previously set parameters..." << endl; 74 | else 75 | cout << "\nNOT RECOGNISED! Continuing with previously set parameters..." << endl; 76 | } 77 | 78 | if (program_choice.compare("full") == 0) 79 | { 80 | focus_full(autofocusing); 81 | } 82 | else if (program_choice.compare("sweep") == 0) 83 | { 84 | focus_sweep(autofocusing); 85 | } 86 | else if (program_choice.compare("tune") == 0) 87 | { 88 | focus_tune(autofocusing); 89 | } 90 | else if (program_choice.compare("test") == 0) 91 | { 92 | focus_test(autofocusing); 93 | } 94 | else if (program_choice.compare("calibrate") == 0) 95 | { 96 | autofocusing.comm_calibrate(); 97 | autofocusing.stop_stage(autofocusing.get_calibrate()); 98 | int path_length; 99 | autofocusing.comm_get_z_len(path_length); 100 | cout << "Path length: " << path_length << endl; 101 | } 102 | else if (program_choice.compare("serial") == 0) 103 | { 104 | serial_send(autofocusing); 105 | } 106 | else if (program_choice.compare("exit") == 0) 107 | { 108 | keep_working = false; 109 | } 110 | else 111 | { 112 | cout << "\nChoice not recognised. Please use the commands provided in parenthesis." << endl; 113 | continue; 114 | } 115 | 116 | times_cycled++; 117 | 118 | } 119 | 120 | 121 | cout << endl; 122 | return 0; 123 | 124 | } 125 | -------------------------------------------------------------------------------- /Raspberry Pi/CPP/focus_everything.h: -------------------------------------------------------------------------------- 1 | // Full Focusing Implementation 2 | 3 | /* This program combines the sweep and fine_tune methods of the autofocusing class to create a fully automated focusing program. 4 | */ 5 | 6 | #ifndef ALLFOCUSING_H 7 | #define ALLFOCUSING_H 8 | 9 | #include "autofocus_class.h" 10 | #include "autofocus_class_initialisation.h" 11 | 12 | 13 | void focus_full(Autofocus&); 14 | void focus_sweep(Autofocus&); 15 | void focus_test(Autofocus&); 16 | void focus_tune(Autofocus&); 17 | 18 | 19 | 20 | 21 | void focus_full(Autofocus &autof) 22 | { 23 | 24 | cout << "\nRunning full version of focusing program..." << endl; 25 | 26 | // Get length of travel 27 | int whole_distance; 28 | autof.comm_get_z_len(whole_distance); 29 | 30 | 31 | // Move to starting position (in this case we are already there, but easily modifiable) 32 | autof.comm_move_to(whole_distance); 33 | autof.stop_stage(); 34 | //cout << "\nMoved back to starting position" << endl; 35 | 36 | 37 | // Run preliminary sweep 38 | autof.sweep(); 39 | 40 | 41 | //cout << "\nGoing to position " << autof.get_max_pos() << " corresponding to image " << autof.get_max_index() << endl; 42 | // Move to maximum 43 | int max_position = autof.get_max_pos(); 44 | autof.comm_move_to(max_position); 45 | autof.stop_stage(); 46 | 47 | 48 | // Reduce number of steps 49 | autof.set_steps(0.5*autof.get_steps()); 50 | 51 | 52 | // Run fine tuning 53 | bool tuning_done = false; 54 | cout << "\nRunning fine tuning" << flush; 55 | tuning_done = autof.fine_tune(); 56 | cout << endl; 57 | 58 | if (tuning_done == true) 59 | { 60 | cout << "\nI think I am done, check this out!" << endl; 61 | sleep(1); 62 | system("raspivid -t 10000"); 63 | } 64 | else 65 | { 66 | cout << "\nWeirdly enough, it returned 'false'" << endl; 67 | } 68 | 69 | return; 70 | 71 | } 72 | 73 | 74 | 75 | void focus_sweep(Autofocus &autof) 76 | { 77 | 78 | cout << "\nRunning sweep program..." << endl; 79 | 80 | 81 | // Get length of travel 82 | int whole_distance; 83 | autof.comm_get_z_len(whole_distance); 84 | 85 | 86 | // Move to starting position (in this case we are already there, but easily modifiable) 87 | autof.comm_move_to(whole_distance); 88 | autof.stop_stage(); 89 | cout << "\nMoved back to starting position" << endl; 90 | 91 | 92 | // Run sweep 93 | autof.sweep(); 94 | 95 | 96 | // Moving to the maximum 97 | char choice; 98 | cout << "\n\tMove to maximum found from sweep (y/n)? "; cin >> choice; 99 | 100 | if (choice == 'y') 101 | { 102 | 103 | cout << "\nGoing to position " << autof.get_max_pos() << " corresponding to image " << autof.get_max_index() << endl; 104 | 105 | autof.comm_move_to(autof.get_max_pos()); 106 | autof.stop_stage(); 107 | 108 | } 109 | 110 | return; 111 | 112 | } 113 | 114 | 115 | 116 | void focus_test(Autofocus &autof) 117 | { 118 | 119 | cout << "\nRunning test program..." << endl; 120 | 121 | 122 | autof.set_output(true); 123 | 124 | // Resolution of image and control values 125 | int number_images = 0; 126 | cout << "\n\tHow many images? "; cin >> number_images; 127 | 128 | 129 | // Do test run 130 | autof.test_run(number_images); 131 | 132 | return; 133 | 134 | } 135 | 136 | 137 | 138 | void focus_tune(Autofocus &autof) 139 | { 140 | 141 | cout << "\nRunning tuning program..." << endl; 142 | 143 | 144 | int whole_distance; 145 | // Get length of travel 146 | autof.comm_get_z_len(whole_distance); 147 | 148 | 149 | // Move to starting position (in this case we are already there, but easily modifiable) 150 | autof.comm_move_to(whole_distance); 151 | autof.stop_stage(); 152 | cout << "\nMoved back to starting position" << endl; 153 | 154 | 155 | // Manual or automatic first adjustment 156 | char choice; 157 | bool try_again = true; 158 | 159 | 160 | while (try_again == true) 161 | { 162 | 163 | cout << "\n\tWould you like to first adjust manually (y/n)? "; cin >> choice; cin.ignore(); 164 | 165 | if (choice == 'y') 166 | { 167 | 168 | cout << "\nWaiting for manual adjustment. Press 'Enter' when done."; cin.ignore(); 169 | 170 | if (autof.get_objective().compare("4x") == 0) 171 | { 172 | autof.set_steps(200); 173 | cout << "\nRunning fine tuning" << flush; 174 | autof.fine_tune(); 175 | } 176 | else if (autof.get_objective().compare("10x") == 0) 177 | { 178 | autof.set_steps(40); 179 | cout << "\nRunning fine tuning" << flush; 180 | autof.fine_tune(); 181 | } 182 | else if (autof.get_objective().compare("40x") == 0) 183 | { 184 | autof.set_steps(10); 185 | cout << "\nRunning fine tuning" << flush; 186 | autof.fine_tune(); 187 | } 188 | else if (autof.get_objective().compare("100x") == 0) 189 | { 190 | autof.set_steps(3); 191 | cout << "\nRunning fine tuning" << flush; 192 | autof.fine_tune(); 193 | } 194 | cout << endl; 195 | 196 | cout << "\nI think I am done!" << endl; 197 | 198 | char trying; 199 | cout << "\n\tTry again with same parameters (y/n)? "; cin >> trying; cin.ignore(); 200 | 201 | if (trying == 'n') 202 | try_again = false; 203 | 204 | } 205 | else 206 | { 207 | 208 | int start_from_here; 209 | cout << "\nStarting point for focus: "; cin >> start_from_here; 210 | autof.comm_move_to(start_from_here); 211 | autof.stop_stage(); 212 | //cout << "\nMoved close to focus point" << endl; 213 | 214 | 215 | // Set initial number of steps 216 | autof.set_steps(200); 217 | 218 | 219 | // Run fine tuning 220 | cout << "\nRunning fine tuning" << flush; 221 | 222 | autof.fine_tune(); 223 | 224 | char trying; 225 | cout << "\n\tTry again (y/n)? "; cin >> trying; 226 | 227 | if (trying == 'n') 228 | try_again = false; 229 | 230 | } 231 | 232 | } 233 | 234 | return; 235 | 236 | } 237 | 238 | void serial_send(Autofocus &autof) 239 | { 240 | 241 | string argument_string; 242 | int argument_int; 243 | string command; 244 | bool serial_commanding = true; 245 | while (serial_commanding) 246 | { 247 | 248 | cout << "\n\tWhat Arduino command would you like to use?\n\t('z_get_length', 'z_get_position', 'z_move', 'z_move_to', 'set_ring_colour', 'set_ring_brightness', 'set_stage_led_brightness', 'exit')\n\n\t" << flush; 249 | cin >> command; 250 | 251 | if (command.compare("z_get_length") == 0) 252 | { 253 | int len; 254 | cout << endl; 255 | autof.comm_get_z_len(len, true); 256 | } 257 | else if (command.compare("z_get_position") == 0) 258 | { 259 | int pos; 260 | cout << endl; 261 | autof.comm_get_z_pos(pos, true); 262 | } 263 | else if (command.compare("z_move") == 0) 264 | { 265 | cout << "\tArgument: " << flush; 266 | cin >> argument_int; cout << endl; 267 | autof.comm_move(argument_int, true); 268 | } 269 | else if (command.compare("z_move_to") == 0) 270 | { 271 | cout << "\tArgument: " << flush; 272 | cin >> argument_int; cout << endl; 273 | autof.comm_move_to(argument_int, true); 274 | } 275 | else if (command.compare("set_ring_colour") == 0) 276 | { 277 | cout << "\tArgument: " << flush; 278 | cin >> argument_string; cout << endl; 279 | autof.comm_set_ring_colour(argument_string, true); 280 | } 281 | else if (command.compare("set_ring_brightness") == 0) 282 | { 283 | cout << "\tArgument: " << flush; 284 | cin >> argument_int; cout << endl; 285 | autof.comm_set_ring_bright(argument_int, true); 286 | } 287 | else if (command.compare("set_stage_led_brightness") == 0) 288 | { 289 | cout << "\tArgument: " << flush; 290 | cin >> argument_int; cout << endl; 291 | autof.comm_set_led_bright(argument_int, true); 292 | } 293 | else if (command.compare("exit") == 0) 294 | { 295 | cout << "\nExiting..." << endl; 296 | serial_commanding = false; 297 | } 298 | else 299 | { 300 | cout << "\n\tCommand not recognised. Please use the commands provided in parenthesis." << endl; 301 | } 302 | 303 | } 304 | 305 | return; 306 | 307 | } 308 | 309 | 310 | #endif 311 | -------------------------------------------------------------------------------- /Raspberry Pi/CPP/makefile: -------------------------------------------------------------------------------- 1 | 2 | FLAGS = -g -o 3 | GRAPHICS = -I.. -Wall -W -ansi -pedantic -Dcimg_use_vt100 -I/usr/X11R6/include -lm -L/usr/X11R6/lib -lpthread -lX11 4 | LINKING = -lboost_system 5 | #-lncurses 6 | 7 | 8 | 9 | ## 'basic' executable and compilation 10 | basic: basic.compile 11 | @echo "\n\n** Running basic **\n" 12 | sudo ./basic.x 13 | 14 | basic.compile: 15 | @echo "\n\n** Compiling basic.cpp **\n" 16 | g++ $(FLAGS) basic.x basic.cpp $(GRAPHICS) $(LINKING) 17 | 18 | 19 | 20 | ## 'testing' executable and compilation 21 | testing: testing.compile 22 | @echo "\n\n** Running executable testing **\n" 23 | sudo ./testing.x 24 | 25 | testing.compile: testing.cpp 26 | @echo "\n\n** Compiling testing.cpp in linux X11 environment **\n" 27 | g++ $(FLAGS) testing.x testing.cpp $(GRAPHICS) $(LINKING) 28 | 29 | 30 | 31 | ## 'focus_applied' executable and compilation 32 | focus_full.run: 33 | @echo "\n\n** Running executable focus_full **\n" 34 | sudo ./focus_full.x 35 | 36 | focus_tuning.run: 37 | @echo "\n\n** Running executable focus_tuning **\n" 38 | sudo ./focus_tuning.x 39 | 40 | focus_sweep.run: 41 | @echo "\n\n** Running executable focus_sweep **\n" 42 | sudo ./focus_sweep.x 43 | 44 | focus_test.run: 45 | @echo "\n\n** Running executable focus_applied **\n" 46 | sudo ./focus_test.x 47 | 48 | focus_everything.run: 49 | @echo "\n\n** Running executable focus_applied **\n" 50 | sudo ./focus_everything.x 51 | 52 | 53 | hocus_focus_everything: focus_everything.cpp 54 | @echo "\n\n** Compiling focus_everything.cpp in linux X11 environment **\n" 55 | g++ $(FLAGS) focus_everything.x focus_everything.cpp $(GRAPHICS) $(LINKING) 56 | 57 | hocus_focus_full: focus_applied.cpp 58 | @echo "\n\n** Compiling focus_full.cpp in linux X11 environment **\n" 59 | g++ $(FLAGS) focus_full.x focus_full.cpp $(GRAPHICS) $(LINKING) 60 | 61 | hocus_focus_tuning: focus_applied2.cpp 62 | @echo "\n\n** Compiling focus_tuning_only.cpp in linux X11 environment **\n" 63 | g++ $(FLAGS) focus_tuning.x focus_tuning_only.cpp $(GRAPHICS) $(LINKING) 64 | 65 | hocus_focus_test: focus_applied2.cpp 66 | @echo "\n\n** Compiling focus_test.cpp in linux X11 environment **\n" 67 | g++ $(FLAGS) focus_test.x focus_test.cpp $(GRAPHICS) $(LINKING) 68 | 69 | hocus_focus_sweep: focus_applied2.cpp 70 | @echo "\n\n** Compiling focus_sweep_only.cpp in linux X11 environment **\n" 71 | g++ $(FLAGS) focus_sweep.x focus_sweep_only.cpp $(GRAPHICS) $(LINKING) 72 | 73 | 74 | 75 | ## 'stack' executable and compilation 76 | stack.run: stack 77 | @echo "\n\n** Running executable stack **\n" 78 | sudo ./stack.x 79 | 80 | stack: stack.cpp 81 | @echo "\n\n** Compiling stack.cpp in linux X11 environment **\n" 82 | g++ $(FLAGS) stack.x stack.cpp $(GRAPHICS) 83 | 84 | 85 | 86 | ## 'edges' executable and compilation 87 | edges.run: 88 | @echo "\n\n** Running executable edges **\n" 89 | sudo ./edges.x 90 | 91 | edges: edges.cpp 92 | @echo "\n\n** Compiling edges.cpp in linux X11 environment **\n" 93 | g++ $(FLAGS) edges.x edges.cpp $(GRAPHICS) $(LINKING) 94 | -------------------------------------------------------------------------------- /Raspberry Pi/CPP/programming_tutorial.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Raspberry Pi/CPP/programming_tutorial.pdf -------------------------------------------------------------------------------- /Raspberry Pi/CPP/programming_tutorial.tex: -------------------------------------------------------------------------------- 1 | % Tutorial 1: 2 | % Programs descriptions 3 | 4 | 5 | 6 | \documentclass[a4paper]{article} 7 | 8 | \usepackage{hyperref} 9 | \usepackage[ruled,noend,vlined]{algorithm2e} 10 | \usepackage{listings} 11 | \usepackage{pifont} 12 | \usepackage{indentfirst} 13 | 14 | \begin{document} 15 | 16 | \title{Automation Tutorial 1: Algorithms and Formulas} 17 | \date{29th August 2013} 18 | \author{Marco Selvi} 19 | \maketitle 20 | 21 | 22 | \section*{Aims} 23 | 24 | The main aim of the \emph{Automation} set of tutorials is to explain how to implement automation in the \textbf{microscope project} of the \textbf{OpenLabTools} initiative. 25 | 26 | In particular, here in \emph{Tutorial 1} we will present the concepts, algorithms and formulas used in the auto-focusing program available in the OpenLabTools GitHub \href{https://github.com/OpenLabTools/Microscope}{repository}. 27 | We will then give a brief overview of other possibilities within this project. 28 | 29 | 30 | \section*{Concepts} 31 | 32 | We now make a brief overview of the fundamental concepts necessary for the correct operation of the microscope. 33 | Here we will maintain a rather abstract approach. 34 | For a more detailed source code description please refer to the \emph{Automation Tutorial 2}. 35 | 36 | \subsection*{\indent{Serial Ports}} 37 | 38 | One of the fundamental things to know in order to implement full automation through C code is \textbf{serial communication} with the Arduino board used (for the Arduino tutorials check \href{https://github.com/OpenLabTools/Microscope/tree/master/Arduino}{here}). 39 | A simple USB connection between the Raspberry Pi and the Arduino board is sufficient to provide serial connection. 40 | The arduino is generally associated with the device \textbf{ttyUSB0}, unless another device is already associated with it. 41 | To check, simply type 42 | 43 | \begin{quote} 44 | ls /dev 45 | \end{quote} 46 | 47 | \noindent 48 | in a terminal window. 49 | Once you know what device to connect to, you can test your serial communication with Python by simply using 50 | 51 | \begin{quote} 52 | import serial\newline 53 | ser = serial.Serial(`name\_{}of\_{}device') 54 | \end{quote} 55 | 56 | Now you can freely communicate to the Arduino by writing into the serial port, and reading outputs from it. 57 | Many ways to do so exist, depending on the libraries and the programming languages used. 58 | We will be programming in C++ and using the \emph{Boost Asio} library whose description can be found \href{http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio.html}{here}. 59 | Details of how this is done are in the \emph{Automation Tutorial 2} document. 60 | 61 | \subsection*{\indent{Image Processing}} 62 | 63 | Another rather obviously important part of our automation routines is image processing. 64 | Again many options exist, depending on the language chosen. 65 | The Python PIL (Python Imaging Library) for example is a very versatile if a little slow imaging library that would serve anyone's purpose. 66 | Here however we will be using the \href{http://cimg.sourceforge.net/}{CImg Library}, optimized for C++ and very portable. 67 | 68 | Image processing is the core of any program that exploits the full functionality of our microscope. 69 | Depending on what we wish to do, it can be a very complex process and of non-trivial implementation. 70 | It can also be highly CPU-demanding, especially with high-quality images.\newline{} 71 | The Raspberry Pi may be a fantastic computer for real-time control and development of projects, and it does indeed provide the perfect platform for the electronics of our microscope. 72 | However, due to its limited processing power, it is not the ideal machine for heavy-duty tasks like image processing of large pictures. 73 | For these reasons we aim to use a reasonably efficient library, and we also tried to keep the resolution of the images rather low wherever possible. 74 | 75 | We will go into more details later, but it should suffice to know for now that the library is used only for the most basic tasks of opening a \emph{jpg} file and displaying images. 76 | All other image processing routines are custom built to save on computational time, with the aim of speeding up the program. 77 | 78 | \subsection*{\indent{Motor Control and Serial Commands}} 79 | 80 | Motor control is what concerns the mechanics of the microscope's stage. 81 | The job of actually controlling the motors and interpreting the commands sent through the serial port is done by the Arduino board, for which we suggest reading through the Arduino tutorials. 82 | For the mechanical structure of the microscope itself, read the Mechanics Tutorials. 83 | What we are interested in at the \emph{automation} stage is what the mechanics can actually do: namely, for auto-focusing, the fact that we can control the vertical movement of the stage with commands sent to the Arduino through the serial port.\newline{} 84 | Other programs might need to make use of the horizontal stage control, also available through the serial commands. Other commands exist to control lighting, read vertical positions, and many more can be added to cover any functionality that future development may make necessary. 85 | 86 | 87 | \section*{Algorithms and Formulas} 88 | 89 | In this section we will give a theoretical description of all the algorithms used in writing the various programs. 90 | Of particular interest are the algorithm for auto-focusing and the algorithm for edge detection used in a sample program on image processing. 91 | 92 | \subsection*{\indent{Canny Edge Detection}} 93 | 94 | The Canny Edge Detection is a rather advanced and functional edge detection algorithm for pictures. 95 | It is a perfect example of image processing implementation, and we will briefly explain here the algorithm on which it is based. 96 | For detailed reference to the code please see \href{https://github.com/OpenLabTools/Microscope/tree/master/Raspberry\%20Pi}{here}. 97 | 98 | This edge detection works in the following way: 99 | 100 | \vspace{12pt} 101 | \begin{algorithm}[H] 102 | \dontprintsemicolon 103 | \KwData{Image to be analysed, in our case a .jpg file} 104 | \KwResult{Edges of said image} 105 | 106 | \Begin 107 | { 108 | \If{Image not in grayscale} 109 | { 110 | Turn image to grayscale\; 111 | } 112 | \BlankLine 113 | Convolve image with smoothing matrix (to eliminate artifacts)\; 114 | Calculate gradient of intensity associated with each pixel\;{} 115 | \BlankLine 116 | Select edges:\\ 117 | { 118 | \If{gradient $<$ lower threshold} 119 | {Turn pixel black\;} 120 | \If{lower threshold $<$ gradient $<$ higher threshold} 121 | {Turn pixel grey $\rightarrow$ minor edges\;} 122 | \If{gradient $>$ higher threshold} 123 | {Turn pixel white $\rightarrow$ major edges\;} 124 | } 125 | \BlankLine 126 | Connect edges:\\ 127 | { 128 | \eIf{minor edge is connected to major edges} 129 | {Turn this minor edge into major edge\;} 130 | {Discard pixel\;} 131 | } 132 | } 133 | \caption{Canny Edge Detection} 134 | \end{algorithm} 135 | \vspace{12pt} 136 | 137 | The algorithm is rather self explanatory, but I would suggest to read quickly through the commented code if you are interested in seeing how this algorithm is implemented, or refer to the \emph{Automation Tutorial 2}. 138 | 139 | \subsection*{\indent{Auto-Focusing}} 140 | 141 | The auto-focusing routine is rather more complex, and separated in sub-routines that implement the various parts of the program needed for the whole to work. 142 | We will here describe only the full and automanted focusing program, while the various subroutines are described in \emph{Automation Tutorial 2}. 143 | 144 | To understand the following algorithm, one must keep in mind that we are using a stepper motor for the vertical movement. 145 | Thus all references to numbers of steps refer to steps associated with the stepper. 146 | The initial and minimum number of steps has to be established depending on the objective in use, as with focal distances and focal depths decreasing we require an ever finer adjustment. 147 | Also the computation of the focusing value for a picture is done through this formula: 148 | 149 | \[ 150 | F = \frac{1}{W H \mu} \sum (I(x,y) - \mu )^2 151 | \] 152 | \noindent 153 | Here $\mu$ is the average intensity of the picture calculated over all the pixels, and $I$ is the intensity of pixel at position $(x,y)$ in the image. 154 | $W$ and $H$ are width and height of the image (in pixels) respectively. 155 | This formula simply represents a standard deviation weighted by the mean, and it is the most effective focusing parameter according to \href{http://www.researchgate.net/publication/4196112_Autofocusing_algorithm_selection_in_computer_microscopy/file/9c96051683d8b3a2d6.pdf}{this paper}. 156 | 157 | \vspace{12pt} 158 | \begin{algorithm}[H] 159 | \dontprintsemicolon 160 | \Begin 161 | { 162 | Set number of steps to start with\; 163 | \BlankLine 164 | Execute sweep:\\ 165 | { 166 | \Indp Take ten images at equal spacings from very close to the objective\; 167 | Compute focusing value for each image\; 168 | Move to position of image with max value\; 169 | } 170 | \BlankLine 171 | Execute tuning:\\ 172 | \While{number of steps $>$ minimum number of steps} 173 | { 174 | \BlankLine 175 | Take picture\; 176 | Compute focusing value for picture (F\_st)\; 177 | \If{Last movement was up} 178 | {Move up\;} 179 | \Else 180 | {Move down\;} 181 | \BlankLine 182 | Take picture\; 183 | Compute focusing value for picture (F\_1)\; 184 | \If{F\_1 $>$ F\_st} 185 | { 186 | Stay there\; 187 | Repeat cycle\; 188 | } 189 | \Else 190 | { 191 | Move in opposite direction (by twice number of steps)\; 192 | Take picture\; 193 | Compute focusing value for picture(F\_2)\; 194 | \BlankLine 195 | \If{F\_2 $>$ F\_st} 196 | { 197 | Stay there\; 198 | Halve number of steps\; 199 | Repeat cycle\; 200 | } 201 | \Else 202 | { 203 | Go back to central position\; 204 | Halve number of steps\; 205 | Repeat cycle\; 206 | } 207 | } 208 | } 209 | Focus position reached within minimum number of steps limitation\; 210 | } 211 | \caption{Focusing} 212 | \end{algorithm} 213 | \vspace{12pt} 214 | 215 | 216 | 217 | 218 | \end{document} 219 | 220 | -------------------------------------------------------------------------------- /Raspberry Pi/CPP/programming_tutorial_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLabTools/Microscope/8fe10c43b6eca532316c28adade6d2d2f28e963d/Raspberry Pi/CPP/programming_tutorial_2.pdf -------------------------------------------------------------------------------- /Raspberry Pi/CPP/programming_tutorial_2.tex: -------------------------------------------------------------------------------- 1 | % Tutorial 2: 2 | % Programs Analysis 3 | 4 | 5 | 6 | \documentclass[a4paper]{article} 7 | 8 | \usepackage{hyperref} 9 | \usepackage[usenames,dvipsnames]{color} 10 | \usepackage[ruled,noend,vlined]{algorithm2e} 11 | \usepackage{listings} 12 | \usepackage{pifont} 13 | \usepackage{indentfirst} 14 | 15 | \lstset{ 16 | backgroundcolor=\color{white}, 17 | basicstyle=\footnotesize, 18 | breakatwhitespace=false, 19 | breaklines=true, 20 | captionpos=b, 21 | commentstyle=\itshape\color{red}, 22 | frame=L, 23 | keepspaces=true, 24 | columns=flexible, 25 | keywordstyle=\bfseries\color{Blue}, 26 | language=C++, 27 | numbers=left, 28 | numbersep=7pt, 29 | numberstyle=\tiny\color{Gray}, 30 | rulecolor=\color{black}, 31 | showspaces=false, 32 | showstringspaces=false, 33 | stepnumber=1, 34 | stringstyle=\color{YellowOrange}, 35 | tabsize=2, 36 | title=\lstname 37 | } 38 | 39 | \begin{document} 40 | 41 | \title{Automation Tutorial 2: Code Description} 42 | \date{8th September 2013} 43 | \author{Marco Selvi} 44 | \maketitle 45 | 46 | 47 | \section*{Aims} 48 | 49 | In this tutorial we will describe in more details what the code written for the microscope's automation actually does. 50 | All programs have been written in C++, with the use of different libraries for image processing and serial port communication. 51 | In the next section we list all packages and libraries necessary for the correct compilation and execution of the programs themselves. 52 | 53 | Remember however that, while this program will compile and run on any platform, it is meant to work on the Raspberry Pi. 54 | This is in particular obvious from the restriction for image capture using the program RaspiStill, available only on the Pi. 55 | If run on any other platform that does not have RaspiStill as a program, the routine will run correctly until the first invocation of 'raspistill', and then crash. 56 | 57 | \section*{Libraries and Packages} 58 | 59 | Here we list all packages necessary for the correct execution of the program, with a short description for each. 60 | Terminal commands for obtaining all packages are at the end of this section. 61 | 62 | \subsection*{Imaging: CoolImage Library} 63 | 64 | For the programs that follow we will use the Cool Image Library, obtainable from \href{http://cimg.sourceforge.net/}{this website}. 65 | This is a template library, contained all in one header file. 66 | It is very easy to use and efficient at run-time, but takes quite a while to compile on the Raspberry Pi (it contains approximately 45,000 lines of code). 67 | To use it, simply include the "CImg.h" file downloadable from the website in the heading of your code and it will work at compile time. 68 | See any example of programs in the next sections to check where to include it. 69 | 70 | \begin{quote} 71 | \emph{We suggest creating a dummy .cpp file containing the library itself and the definition of the components used, so that it can be compiled separately and then linked as an object. 72 | A header file of similar type might be useful also. 73 | We have not considered this possibility until the writing of this tutorial because software development was done on a computer that could handle compilation of the CImg.h file easily, but if you plan to do software development on the Pi this is definitely an option to explore.} 74 | \end{quote} 75 | 76 | \subsection*{Serial Communication: Boost Asio Library} 77 | 78 | Communication over the serial port is done using the Boost Asio library (see \href{http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio.html}{here} for documentation). 79 | This library provides rather simple to implement (if hard to devise) communication with the Arduino. 80 | Opening a serial port with this library allows the user to use the serial communication as a stream not dissimilar from the 'iostream' available from the C++ inbuilt libraries. 81 | Commands can be written to the stream and outputs can be read from it. 82 | However... 83 | 84 | A NOTE of caution: the non-asynchronous functions used to read from the serial port block until the buffer used to read into is full (so they must read at least one character, if the buffer used if of such size). 85 | If you are developing your own software using this library, be sure that whenever a 'read' function is called on the serial port stream there will be some output to read. 86 | Otherwise, your program will block forever. 87 | Alternatively, try using the asynchronous read functions provided in the boost libraries. 88 | If you can figure out how. 89 | 90 | \subsection*{Terminal Commands to Install Libraries} 91 | 92 | You will need the 'imagemagick' package to handle window display from the CoolImage library through the 'CImgDisplay' class. 93 | 94 | You will also need to make sure that the X11 video libraries are installed. 95 | These are generally already installed in Raspbian, but checking can't hurt. 96 | 97 | As we said, the CoolImage library is used by simply including the header file, so no package is installed for it. 98 | 99 | Just to be on the safe side, or if you want to do some testing, you may install the Python imaging library as well. 100 | It is not as efficient as the CoolImage library, so since our programs are rather speed-sensitive we opted for the latter, but it is a good first-stage development tool. 101 | 102 | So the commands to use to install everything are 103 | 104 | \begin{quote} 105 | sudo apt-get update 106 | sudo apt-get install libx11-dev imagemagick python-imaging libboost-all-dev 107 | \end{quote} 108 | 109 | And you are done installing stuff. 110 | Now for the real programming... 111 | 112 | 113 | \section*{Edge Recognition} 114 | 115 | Here we report an implementation of the Canny Edge Recognition \href{http://en.wikipedia.org/wiki/Canny_edge_detector}{algorithm} as an example of how to do image processing with the CoolImage library. 116 | The relevant code files are found \href{https://github.com/OpenLabTools/Microscope/tree/master/Raspberry%20Pi}{here}. 117 | 118 | As it can be seen from a quick analysis, the 'edges.cpp' file is a very basic user interface, while all the computation is done in the header file `edgedetection\_class.h'. 119 | We will therefore skip a detailed analysis of the former, and concentrate on what the latter does. 120 | 121 | \subsection*{edgedetection\_class.h} 122 | 123 | This file handles all the processes needed to detect edges in an image using the Canny Edge Detection algorithm mentioned above. 124 | We use `.jpg' files because they have only one layer and are therefore more easily analysed. 125 | The CoolImage library can of course work with multi-layer images such as `.bmp' as well, but the code will need heavy remodeling to work with more complex images. 126 | To make your life easier, just convert images to `.jpg'. 127 | Edges don't need multi-layering anyway. 128 | 129 | The file `edgedetection\_class.h' (as the name suggests) containes a class whose methods do everything in the edge detection algorithm. 130 | The method invoked by `edges.cpp' is `canny\_edge\_detection()' that takes no arguments. 131 | This method then invokes all other methods in the class. 132 | Check all other methods in the complete header file at the link mentioned above. 133 | We don't report them here to avoid clutter. 134 | 135 | This is the code for the principal method, with relevant comments. 136 | The comments should be self explanatory. 137 | 138 | \lstinputlisting[firstline=194, lastline=327, firstnumber=194]{edgedetection_class.h} 139 | 140 | \section*{Microscope Control} 141 | 142 | Now we can start tackling more complex tasks, useful for the control of the microscope. 143 | In particular, we need to make all functions and methods `cooperate' efficiently and as fast as possible. 144 | The algorithm used in this program is available in the Tutorial 1 PDF. 145 | Here we analyse the methods used in the steps of the algorithm. 146 | 147 | \subsection*{Image Acquisition} 148 | 149 | To acquire images to be used in the focusing algorithm, we use the inbuilt `raspistill' program available with the Raspberry Pi camera libraries. 150 | To do so, we simply call a `system()' function, which allows to call terminal programs from within a C++ program. 151 | 152 | \begin{lstlisting} 153 | system("raspistill -n -w 480 -h 360 -o test.jpg"); 154 | \end{lstlisting} 155 | 156 | \subsection*{Image Analysis} 157 | 158 | We use the CImg library to open the images, and the use the focusing formula contained in this method to analyse them. 159 | 160 | \lstinputlisting[firstline=472, lastline=508, firstnumber=472]{autofocus_class.h} 161 | 162 | This is used to compute a focusing value for each picture taken with `raspistill'. 163 | Then the program uses these values in the previous algorithm to decide what to do. 164 | 165 | \subsection*{Arduino Control} 166 | 167 | To control the Arduino, we use the following method. 168 | 169 | \lstinputlisting[firstline=1150, lastline=1356, firstnumber=1150]{autofocus_class.h} 170 | 171 | The commands we pass are prebuilt in the code loaded on the Arduino, available \href{https://github.com/OpenLabTools/Microscope/tree/master/Arduino}{here}. 172 | What they do is pretty straightforward, and at the link above a full description of all the commands available is provided. 173 | Note that we use the `boost::asio::read\_some()' and the `boost::asio::read\_until()' functions to read the output from the Arduino and save it in strings we can use to interpret it. 174 | It is important to make sure that every time we read an output, there is an output to read. 175 | Otherwise these functions will block. 176 | For a complete documentation of these functions check the links available \href{http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/overview/serial\_ports.html}{here}. 177 | Other formulas are available for the usage of Arduino controls from the main program. 178 | Check the full code for details. 179 | They all contain the necessary comments to understand their functionality. 180 | 181 | \subsection*{Algorithm Implementation} 182 | 183 | The implementation of the tuning algorithm is in this function. 184 | 185 | \lstinputlisting[firstline=587, lastline=794, firstnumber=587]{autofocus_class.h} 186 | 187 | The passages are directly correlated to the algorithm in Tutorial 1. 188 | We use a (rather arbitrary) minimum number of steps for each objective, that should give a sufficient resolution to find a focus point while disregarding changes due to noise. 189 | We also use an acceptance threshold (default is 99\%) on the focus value, to account for noise influence. 190 | Code is available for a more automated focusing program in the file \href{https://github.com/OpenLabTools/Microscope/tree/master/Raspberry\%20Pi}{focus\_everything.h}. 191 | For more details check the comments on the code provided. 192 | 193 | \subsection*{Other Files} 194 | 195 | The file `focus\_everything.h' implements different usages of the autofocus class. 196 | Again check comments for descriptions. 197 | 198 | The file `autofocus\_class\_initialisation.h' contains an implementation of instructions to initialise the autofocus class. 199 | It also provides the possibility to use a default initialisation, that will assume the objective in use on the microscope is a `4x'. 200 | 201 | The file `focus\_everything.cpp' is the main file that puts together all the header files and provides the user interface through terminal. 202 | Through this file it is possible to use all methods provided by the autofocus class recursively, and decide whether to save the output of each operation. 203 | 204 | The `Makefile' provided allows to compile and launch all programs available. 205 | The flags implemented here are necessary for the correct usage of the boost libraries and the CImg library, linking all other useful libraries. 206 | 207 | All files can be found \href{https://github.com/OpenLabTools/Microscope/tree/master/Raspberry\%20Pi}{here}, with relevant comments describing all the functionalities. 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | \end{document} 217 | -------------------------------------------------------------------------------- /Raspberry Pi/Python/openlabtools-microscope/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'james' 2 | -------------------------------------------------------------------------------- /Raspberry Pi/Python/openlabtools-microscope/interface.py: -------------------------------------------------------------------------------- 1 | __author__ = 'james' 2 | 3 | import serial 4 | from time import sleep 5 | 6 | 7 | class Microscope: 8 | """Abstracts the serial command interface to the OpenLabTools microscope""" 9 | 10 | def __init__(self, port): 11 | """Opens the serial connection given a port name""" 12 | 13 | #Open connection 14 | self.ser = serial.Serial(port, 9600) 15 | 16 | #Flash the DTR pin to reset the Arduino (Needed so the Arduino is in a known state) 17 | self.ser.setDTR(False) 18 | sleep(0.22) 19 | self.ser.setDTR(True) 20 | 21 | #Read the first four lines from the Stepper shield initialization 22 | for x in range(4): 23 | self.ser.readline() 24 | 25 | def __del__(self): 26 | """Closes the serial connection on object deletion""" 27 | self.ser.close() 28 | 29 | def run_command(self, command): 30 | """Writes command to the interface and returns any response. 31 | 32 | Raises an exception if any error returned from Arduino 33 | 34 | """ 35 | 36 | self.ser.write(command) 37 | 38 | line = '' 39 | ret = '' 40 | 41 | #Keep reading lines until the Arduino indicates command finished 42 | while line != 'OK\r\n': 43 | line = self.ser.readline() 44 | if line.startswith('ERR:'): 45 | raise Exception(line) 46 | if line.startswith('RETURN:'): 47 | ret = line[8:] 48 | 49 | return ret 50 | 51 | @staticmethod 52 | def check_axis(axis): 53 | """Checks that the axis string corresponds to a valid axis""" 54 | if axis not in ['x', 'y', 'z']: 55 | raise Exception('Not a valid axis!') 56 | 57 | def calibrate(self): 58 | """Runs the calibration procedure for the Microscope""" 59 | 60 | #The only blocking command(and takes for forever), so longer timeout 61 | self.ser.timeout = 30 62 | command = 'calibrate\n' 63 | self.run_command(command) 64 | self.ser.timeout = 1 65 | 66 | def is_calibrated(self): 67 | """Check if the microscope is calibrated""" 68 | command = 'is_calibrated\n' 69 | line = self.run_command(command) 70 | if line == '1': 71 | return True 72 | else: 73 | return False 74 | 75 | def get_length(self, axis): 76 | """Returns the length of the specified axis""" 77 | command = axis + '_get_length\n' 78 | length = self.run_command(command) 79 | return int(length) 80 | 81 | def get_position(self, axis): 82 | """Get the current position of the specified axis""" 83 | self.check_axis(axis) 84 | command = axis + '_get_position\n' 85 | position = self.run_command(command) 86 | return int(position) 87 | 88 | def get_distance_to_go(self, axis): 89 | """Get the distance between current and target position of the specified axis""" 90 | self.check_axis(axis) 91 | command = axis + '_get_distance_to_go\n' 92 | distance = self.run_command(command) 93 | return int(distance) 94 | 95 | def move(self, axis, steps): 96 | """Move the specified axis relative to current position""" 97 | self.check_axis(axis) 98 | command = axis + '_move ' + str(steps) + '\n' 99 | self.run_command(command) 100 | 101 | def move_to(self, axis, position): 102 | """Move the specified axis to an absolute position""" 103 | self.check_axis(axis) 104 | command = axis + '_move_to' + str(position) + '\n' 105 | self.run_command(command) 106 | 107 | def set_ring_colour(self, colour): 108 | """Set the colour of the ring LED""" 109 | command = 'set_ring_colour ' + colour + '\n' 110 | self.run_command(command) 111 | 112 | def set_ring_brightness(self, brightness): 113 | """Set the brightness of the ring LED""" 114 | command = 'set_ring_brightness ' + str(brightness) + '\n' 115 | self.run_command(command) 116 | 117 | def set_stage_led_brightness(self, brightness): 118 | """Set the brightness of the stage LED""" 119 | command = 'set_stage_led_brightness ' + str(brightness) + '\n' 120 | self.run_command(command) 121 | -------------------------------------------------------------------------------- /Raspberry Pi/Python/openlabtools-microscope/server.py: -------------------------------------------------------------------------------- 1 | __author__ = 'james' 2 | 3 | import os 4 | from datetime import datetime 5 | 6 | from twisted.web import xmlrpc, server 7 | from interface import Microscope 8 | 9 | 10 | class MicroscopeServer(xmlrpc.XMLRPC): 11 | """ Implements an XML-RPC server allowing remote control of the OpenLabTools microscope over a network 12 | 13 | Exposes all Arduino commands, plus photo and video recording commands 14 | 15 | """ 16 | 17 | def __init__(self, serial_port, allowNone=False, useDateTime=False): 18 | """Initializes the class with serial port name of Arduino""" 19 | xmlrpc.XMLRPC.__init__(self, allowNone, useDateTime) 20 | self.microscope = Microscope(serial_port) 21 | 22 | def xmlrpc_calibrate(self): 23 | self.microscope.calibrate() 24 | 25 | def xmlrpc_is_calibrated(self): 26 | calibrated = self.microscope.is_calibrated() 27 | return calibrated 28 | 29 | def xmlrpc_get_length(self, axis): 30 | axis = self.microscope.get_length(axis) 31 | return axis 32 | 33 | def xmlrpc_get_position(self, axis): 34 | position = self.microscope.get_position(axis) 35 | return position 36 | 37 | def xmlrpc_get_distance_to_go(self, axis): 38 | axis = self.microscope.get_distance_to_go(axis) 39 | return axis 40 | 41 | def xmlrpc_move(self, axis, position): 42 | self.microscope.move(axis, position) 43 | 44 | def xmlrpc_move_to(self, axis, position): 45 | self.microscope.move_to(self, axis, position) 46 | 47 | def xmlrpc_set_ring_colour(self, colour): 48 | self.microscope.set_ring_colour(colour) 49 | 50 | def xmlrpc_set_ring_brightness(self, brightness): 51 | self.microscope.set_ring_brightness(brightness) 52 | 53 | def xmlrpc_set_stage_led_brightness(self, brightness): 54 | self.microscope.set_stage_led_brightness(brightness) 55 | 56 | def xmlrpc_take_picture(self): 57 | """Takes a photograph with datetime string for filename""" 58 | 59 | #Not hugely portable, definitely unstable, need better method 60 | now = datetime.now() 61 | filename = ("%s_%s_%s__%s_%s_%s.jpg" % (now.year, now.month, now.day, now.hour, now.minute, now.second)) 62 | os.system(("raspistill -n -t 0 -o %s &" % filename)) 63 | 64 | def xmlrpc_take_video(self, duration): 65 | """Records a video of specified duration with datetime string for filename""" 66 | now = datetime.now() 67 | filename = ("%s_%s_%s__%s_%s_%s.h264" % (now.year, now.month, now.day, now.hour, now.minute, now.second)) 68 | os.system(("raspivid -n -t %s -o %s" %(duration, filename))) 69 | 70 | 71 | 72 | #Start running the server 73 | if __name__ == '__main__': 74 | from twisted.internet import reactor 75 | r = MicroscopeServer('/dev/tty.usbmodemfd121', True) 76 | reactor.listenTCP(7080, server.Site(r)) 77 | reactor.run() 78 | 79 | 80 | -------------------------------------------------------------------------------- /Raspberry Pi/Python/openlabtools-microscope/tracker.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | import numpy as np 4 | from scipy import interpolate 5 | 6 | import cv2 7 | 8 | from interface import Microscope 9 | 10 | 11 | class WormTracker(): 12 | """Class for worm tracking algorithm""" 13 | 14 | def nothing(x, y): 15 | #Placeholder as trackbar requires callback 16 | pass 17 | 18 | def __init__(self, serial_port, camera): 19 | """Initializes the class with serial interface/camera names, 20 | algorithm control parameters. 21 | 22 | Arguments: 23 | serial_port -- String of name for the serial interface for the 24 | microscope Arduino - e.g. 'dev/tty.usb' 25 | camera -- Integer for the V4L2 video device name e.g. 0 from 26 | '/dev/video0' 27 | 28 | """ 29 | self.create_gui() 30 | 31 | #Setup camera and video recording 32 | self.camera = cv2.VideoCapture(camera) 33 | self.width = int(self.camera.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH)) 34 | self.height = int(self.camera.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT)) 35 | self.camera.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, self.width) 36 | self.camera.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, self.height) 37 | 38 | #Kernel for morphological opening/closing operation 39 | self.kernel = np.ones((3, 3), np.uint8) 40 | 41 | #Variables for controlling stage 42 | self.microscope = Microscope(serial_port) 43 | self.microscope.set_ring_colour('FF0000') 44 | self.last_step_time = datetime.now() 45 | 46 | #Use for FPS calculation 47 | self.last_frame = cv2.getTickCount() 48 | 49 | #Skeltonisation 50 | self.worm_spline = np.zeros((1001, 1, 2), dtype=np.int) 51 | self.tail = np.zeros((2,), dtype=np.int) 52 | self.head = np.zeros((2,), dtype=np.int) 53 | 54 | def change_kernel(self, size): 55 | '''Generate new kernel patch for morphological opening/closing''' 56 | size = size*2 + 1 57 | self.kernel = np.ones((size, size), np.uint8) 58 | 59 | def create_gui(self): 60 | """"Defines the HighGUI elements """ 61 | cv2.namedWindow('Preview') 62 | cv2.createTrackbar('Tracking Off/On', 'Preview', 0, 1, self.nothing) 63 | cv2.createTrackbar('Threshold', 'Preview', 0, 1, self.nothing) 64 | cv2.createTrackbar('Threshold Value', 'Preview', 0, 255, self.nothing) 65 | cv2.createTrackbar('Step Interval', 'Preview', 0, 1000, self.nothing) 66 | cv2.createTrackbar('Margin', 'Preview', 0, 200, self.nothing) 67 | cv2.createTrackbar('Step Size', 'Preview', 0, 20, self.nothing) 68 | cv2.createTrackbar('Contour', 'Preview', 0, 1, self.nothing) 69 | cv2.createTrackbar('Adaptive', 'Preview', 0, 1, self.nothing) 70 | cv2.createTrackbar('Adaptive Value', 'Preview', 0, 40, self.nothing) 71 | cv2.createTrackbar('Adaptive Size', 'Preview', 1, 40, self.nothing) 72 | cv2.createTrackbar('Gaussian', 'Preview', 0, 1, self.nothing) 73 | cv2.createTrackbar('Kernel Size', 'Preview', 1, 20, self.change_kernel) 74 | cv2.createTrackbar('Opening', 'Preview', 0, 20, self.nothing) 75 | cv2.createTrackbar('Closing', 'Preview', 0, 20, self.nothing) 76 | cv2.createTrackbar('Skeleton', 'Preview', 0, 1, self.nothing) 77 | cv2.createTrackbar('Smoothing', 'Preview', 0, 1000, self.nothing) 78 | 79 | #Set default values 80 | cv2.setTrackbarPos('Threshold Value', 'Preview', 100) 81 | cv2.setTrackbarPos('Step Interval', 'Preview', 500) 82 | cv2.setTrackbarPos('Margin', 'Preview', 100) 83 | cv2.setTrackbarPos('Step Size', 'Preview', 2) 84 | 85 | def read_trackbars(self): 86 | """Read trackbar values""" 87 | self.tracking = bool(cv2.getTrackbarPos('Tracking Off/On', 'Preview')) 88 | self.show_threshold = bool(cv2.getTrackbarPos('Threshold', 'Preview')) 89 | self.threshold = cv2.getTrackbarPos('Threshold Value', 'Preview') 90 | self.step_interval = cv2.getTrackbarPos('Step Interval', 'Preview') 91 | self.margin = cv2.getTrackbarPos('Margin', 'Preview') 92 | self.step_size = cv2.getTrackbarPos('Step Size', 'Preview') 93 | self.draw_contour = bool(cv2.getTrackbarPos('Contour', 'Preview')) 94 | self.precision = cv2.getTrackbarPos('Precision', 'Preview') 95 | self.adaptive = bool(cv2.getTrackbarPos('Adaptive', 'Preview')) 96 | self.adaptive_value = cv2.getTrackbarPos('Adaptive Value', 'Preview') 97 | self.adaptive_size = cv2.getTrackbarPos('Adaptive Size', 'Preview') 98 | self.adaptive_gauss = bool(cv2.getTrackbarPos('Gaussian', 'Preview')) 99 | self.opening = cv2.getTrackbarPos('Opening', 'Preview') 100 | self.closing = cv2.getTrackbarPos('Closing', 'Preview') 101 | self.skeleton = bool(cv2.getTrackbarPos('Skeleton', 'Preview')) 102 | self.smoothing = cv2.getTrackbarPos('Smoothing', 'Preview') 103 | 104 | def find_worm(self): 105 | """Threshold and contouring algorithm to find centroid of worm""" 106 | self.img_gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY) 107 | 108 | if self.adaptive: 109 | #Perform adaptive thresholding 110 | size = self.adaptive_size*2 + 1 111 | 112 | if self.adaptive_gauss: 113 | mode = cv2.ADAPTIVE_THRESH_MEAN_C 114 | else: 115 | mode = cv2.ADAPTIVE_THRESH_GAUSSIAN_C 116 | 117 | self.img_thresh = cv2.adaptiveThreshold(self.img_gray, 255, 118 | mode, 119 | cv2.THRESH_BINARY_INV, 120 | size, 121 | self.adaptive_value) 122 | 123 | else: 124 | #Simple Threshold 125 | ret, self.img_thresh = cv2.threshold(self.img_gray, self.threshold, 126 | 255, cv2.THRESH_BINARY_INV) 127 | 128 | if self.opening != 0: 129 | #Morphological Opening 130 | self.img_thresh = cv2.morphologyEx(self.img_thresh, 131 | cv2.MORPH_OPEN, 132 | self.kernel, 133 | iterations=self.opening) 134 | 135 | if self.closing != 0: 136 | #Morphological Closing 137 | self.img_thresh = cv2.morphologyEx(self.img_thresh, 138 | cv2.MORPH_CLOSE, 139 | self.kernel, 140 | iterations=self.closing) 141 | 142 | #Copy image to allow displaying later 143 | img_contour = self.img_thresh.copy() 144 | contours, hierarchy = cv2.findContours(img_contour, cv2.RETR_TREE, 145 | cv2.CHAIN_APPROX_NONE) 146 | 147 | #Find the biggest contour 148 | worm_area = 0 149 | for contour in contours: 150 | area = cv2.contourArea(contour) 151 | if area > worm_area: 152 | self.worm = contour 153 | worm_area = area 154 | 155 | #Compute the centroid of the worm contour 156 | moments = cv2.moments(self.worm) 157 | self.x = int(moments['m10']/moments['m00']) 158 | self.y = int(moments['m01']/moments['m00']) 159 | 160 | def skeletonise(self): 161 | '''Perform skeletonisation and determine location of head and tail''' 162 | x_in = self.worm[:, 0, 0] 163 | y_in = self.worm[:, 0, 1] 164 | 165 | tck, u = interpolate.splprep([x_in, y_in], per=True, s=self.smoothing, 166 | quiet=1) 167 | 168 | points = np.arange(0, 1.001, 0.001) 169 | 170 | spline = interpolate.splev(points, tck, der=0) 171 | x = spline[0] 172 | y = spline[1] 173 | self.worm_spline[:, 0, 0] = x 174 | self.worm_spline[:, 0, 1] = y 175 | 176 | d = interpolate.splev(points, tck, der=1) 177 | dx = d[0] 178 | dy = d[1] 179 | 180 | dd = interpolate.splev(points, tck, der=2) 181 | ddx = dd[0] 182 | ddy = dd[1] 183 | 184 | k = dx*ddy - dy*ddx 185 | k = np.absolute(k) 186 | k = k/((dx**2 + dy**2)**1.5) 187 | 188 | tail_n = np.argmax(k) 189 | k[tail_n-125:tail_n+125] = 0 190 | head_n = np.argmax(k) 191 | 192 | self.tail[0] = int(x[tail_n]) 193 | self.tail[1] = int(y[tail_n]) 194 | 195 | self.head[0] = int(x[head_n]) 196 | self.head[1] = int(y[head_n]) 197 | 198 | def move_stage(self): 199 | '''Move the stage if the worm gets near the edge of image''' 200 | now = datetime.now() 201 | elapsed_time = ((now - self.last_step_time).microseconds)/1000 202 | 203 | if self.tracking and elapsed_time > self.step_interval: 204 | self.last_step_time = now 205 | if self.x < self.margin: 206 | self.microscope.move('x', -1*self.step_size) 207 | print 'Moving Left' 208 | 209 | if self.x > (self.width - self.margin): 210 | self.microscope.move('x', self.step_size) 211 | print 'Moving Right' 212 | 213 | if self.y < self.margin: 214 | self.microscope.move('y', -1*self.step_size) 215 | print 'Moving Up' 216 | 217 | if self.y > (self.height - self.margin): 218 | self.microscope.move('y', self.step_size) 219 | print 'Moving Down' 220 | 221 | def update_gui(self): 222 | '''Update GUI with image and draw feature markers''' 223 | if self.show_threshold: 224 | self.img = cv2.cvtColor(self.img_thresh, cv2.COLOR_GRAY2BGR) 225 | 226 | if self.draw_contour: 227 | if self.skeleton: 228 | cv2.drawContours(self.img, [self.worm_spline], 229 | -1, (255, 0, 0), 2) 230 | else: 231 | cv2.drawContours(self.img, [self.worm], -1, (255, 0, 0), 2) 232 | 233 | #Draw markers for centroid and boundry 234 | cv2.circle(self.img, (self.x, self.y), 5, (0, 0, 255), -1) 235 | cv2.rectangle(self.img, (self.margin, self.margin), 236 | (self.width-self.margin, self.height-self.margin), 237 | (0, 255, 0), 238 | 2) 239 | 240 | #If skeletonise draw markers for head and tail 241 | if self.skeleton: 242 | cv2.circle(self.img, (self.tail[0], self.tail[1]), 243 | 5, (0, 255, 255), -1) 244 | cv2.circle(self.img, (self.head[0], self.head[1]), 245 | 5, (255, 255, 0), -1) 246 | 247 | #Show image 248 | cv2.imshow('Preview', self.img) 249 | cv2.waitKey(1) 250 | 251 | def run(self): 252 | """Runs the worm tracking algorithm indefinitely""" 253 | 254 | for i in range(100): 255 | #Spool off 100 images to allow camera to auto-adjust 256 | self.img = self.camera.read() 257 | 258 | while True: 259 | 260 | self.read_trackbars() 261 | ret, self.img = self.camera.read() 262 | self.find_worm() 263 | 264 | if self.skeleton: 265 | self.skeletonise() 266 | 267 | self.update_gui() 268 | self.move_stage() 269 | 270 | #FPS calculations 271 | now = cv2.getTickCount() 272 | fps = cv2.getTickFrequency()/(now - self.last_frame) 273 | self.last_frame = now 274 | 275 | print fps 276 | --------------------------------------------------------------------------------