Introduction: The ROTAforMI: a RObotic TAble for Microscopy

About: I am a curious scientist and dedicated teacher, supported by two loving little assistants.

The ROTAforMI is a versatile robotic device for controlling the position and orientation of a microscope slide using four degrees of freedom. This prototype is a complementary development of the idea behind the Roto-microscope project. It was inspired by related projects of servo motors-controlled micromanipulators and 3D micro scanners.

The device is entirely 3D printed and is actioned by four small servos controlled by one Arduino Nano microcontroller. The device can be controlled manually using two micro joysticks (and possibly also automatically via a programmed sequence of movements). In addition, a Bluetooth remote can take snapshots with a smartphone's camera.

Supplies

For this project, you need:

HARDWARE

  1. 3D printer. All the parts have been printed using PLA filaments. We have used a resolution of up to 0.3 mm to speed up the printing of the main body and the microscope table support. We have used Creality Ender 5 Pro for this project.
  2. An Arduino Nano + Expansion board. An Arduino nano with the expansion board and LCD as in our previous project (e.g. The Sand slicer).
  3. Five SG90-9G Micro servo motors. Four are used for moving the platforms, and one is to press the Bluetooth remote button to take pictures from the smartphone.
  4. An LCD Screen 1602A shield. We used it as we wanted to try this shield as it t has a convenient keypad integrated with the LCD.
  5. Two joystick modules:For manual control of the ROTAforMI positions.
  6. Connecting cables.
  7. A support platform for electronics. See the one in our previous The Sand slicer project.
  8. A Bluetooth shutter. A simple one-button shutter to control the camera on the camera smartphone.
  9. Two ABEC-9 608Z bearings.
  10. Superglue.
  11. A power bank battery.
  12. Microscope slides (62x20 mm).
  13. NUTS and SCREWS:
  • Two machine screws (4x80 mm).
  • 2 M4 nuts.

3D PRINTED PARTS

The files in STL format of all parts are provided as supporting files. We have used the Prusa Slicer for this project.

Step 1: Assembly of the Slide Support and Rotation Stage

The first step consists of assembling the slide support and rotation stage.

First, you need to print parts A-C, gears 1 and 2 and rack 1. Print PartB2a and B2b vertically to keep the central hole free of supporting material.

Then, follow the instruction shown in Figures 1-3.

  • Add gear 1 to the slide support, as shown in figure 1.
  • Add the two bearings to PartB1 and B3.
  • Glue rack 1 to the PartB2b. The base of the rack should be aligned with the bottom of the square rod.
  • Insert the slide support terminal rods in the bearings' central hole. The longer rod needs to be inserted in the bearing hole by PartB3.
  • Unite all the parts as indicated in Step5b and insert the two screws in the central holes of the squared bars B2a and B2b. Use a screwdriver for this purpose. Add the two nuts to the end.
  • Add the Servo1 screwing it to the PartC as indicated in the figure.
  • Finally, add gear 2.

The microscopy slides for the holder should have a size of~ 62x20 mm.

Step 2: Assembly of the Z-axis Motion Stage

The second step consists of the assembly of the Z-axis motion stage.

First, you must print parts C, gears 3 and rack 2.

Then, following the instruction shown in Figure 4.

  • Insert the slide support and rotation stage into the printed Part C. You might try to apply a little grease to lubricate the walls of Part B1 and PartB3 to smooth the Z motion.
  • Attach the Gear 3 to the Servo2.
  • Fix two screws in the Servo to Part C, as shown in the figure. 
  • Glue the Rank 2 on the centre of the bottom of the back wall of PartC. The base of the Rank2 must align with the base of PartC, as shown in the figure.

The Z-axis translation and rotation stage is now completed.

Step 3: Assembly of the X-Motion Stage

The third step consists of the assembly of the X-axis motion platform.

First, you must print parts D, E, and 4.

Then, following the instruction shown in Figure 5.

  1. Insert the Z-translation and rotation stage in platform D, as shown in the Figure. You might try to apply a little grease to lubricate X motion.
  2. Fix with four screws Servo 3 and 4 to the PartD using two screws. 
  3. Attach the Grear4 to the Servo3. 
  4. Attach with two screws the PartE with the servos to the PartE using two screw holes in the central part.

The XZ-axis translation and rotation stage is now completed.

Step 4: Assembly of the Y-Motion Stage

The last assembly step consists of the assembly of the Y-axis motion platform.

First, you must print parts F and 5.

Then, following the instruction shown in the Figure 6.

  1. Attach the Grear5 to the Servo4. 
  2. Insert the XZ-translation and rotation stage in platform F as shown in the Figure. You might try to apply a little grease to lubricate the Y motion if necessary. 

The ROTAforMI device is now complete. Congratulations! 

Step 5: Microcontroller

The ROTAforMI microcontroller is based on one Arduino Nano connected to 5 servos, two joystick modules and an LCD. Four servos are used for the translation and rotation of the slide support, and one is for controlling a Bluetooth remote that can be used to activate a camera for taking pictures.

The connections are shown in the diagram, and the code for the microcontroller is given below. In addition, we have mounted the electronic board of the prototype on support. The construction of the metallic support and the 3D models of the electronic boards and module components are described in our previous Magic SandSlicer project. For this project, you need to print a second joystick module support.


NOTE: Do not power ROTAforMI using the USB of your laptop, but use an external power supply. We have used a power bank. First, upload the program on Arduino nano and insert it into the expansion board.


In the program, The step of rotation and translation can be changed using the two variables:


// set the translation and rotation steps
int rstep = 3; // rotation steps
int tstep = 5; // translation step


The variables set the initial positions of the servos:


int xpos = 90; // n. steps z
int ypos = 90; // n. steps y
int zpos = 90; // n. steps z
int rpos = 90;  // n. rot steps


The max and min values of the variables are set as:

int maxpx = 175;  // max steps x
int maxpy = 175;  // max steps y
int maxpz = 175; // max steps z
int maxpr = 175;  // max rot step

int minpx = 30;  // max steps x
int minpy = 30;  // max steps y
int minpz = 110; // max steps z
int minpr = 30;  // max rot step


Before compiling, you also need to install the library for controlling the servo motors (Servo), and the ICS-controlled LCD (iquidCrystal_I2C).

THE ARDUINO CODE


/*
    PROGRAM NAME: ROTAforMI CONTROLLER

    DESCRIPTION : This program is written for the Arduino Nano microcontroller and it is used to control the ROTAforMI.
                  The two joystick modules are used to move the 3 axes of the platform and to rotate the slide support.
                  The joystick buttons are used to take pictures using the smartphone shutter.

    LCD MENU    :
                  X axis/steps:  translation steps of the ROTAforMI table along X.
                  Y axis/steps:  translation steps of the ROTAforMI table along Y.
                  Z axis/steps:  translation steps of the ROTAforMI table along Z.
                  Slide Rotation/degrees:  Rotation steps (in degrees) of the microscope slide.

                  Left Joystick Button: action the bluetooth remote.

    AUTHOR : (c) 2022 Danilo Roccatano
    VERSION: 1.0
    DATE   : August 2022

*/

// include Arduino stepper motor library
#include <Servo.h>
#include <Wire.h>
// include the library code for the LCD
#include <LiquidCrystal_I2C.h>

//LCD settings
// Set the LCD address to 0x27 for a 16 chars and 2 line display
const uint8_t I2C_ADDRESS = 0x27; //watch video. use I2C Scanenr to get the address
const uint8_t LCD_CHAR = 16;
const uint8_t LCD_LINE = 2;

char TITLE_LCD[3][20] = {"The ROTAforMI", "v.1. D.Roccatano ", "Use Joysticks"};
char MENU_TITLE[4][20] = {"X-steps:", "Y-steps:", "Z-steps:", "Rot-degrees:"};

// Joystick 1 module setup
#define XJOY1_PIN A1                    //Move along X axis 
#define YJOY1_PIN A0                    //Move along Y axis 
#define BUTJOY1_PIN 11                  //joystick 1 button 

// Joystick 2 module setup
#define XJOY2_PIN A4                   //Rotate around slide axis 
#define YJOY2_PIN A5                   //Move along Z axis 
//#define BUTJOY2_PIN 10                  //joystick 2 button

// set the translation and rotation steps
int rstep = 3; // rotation steps
int tstep = 5; // translation step

int xpos = 90;  // n. steps x
int ypos = 90;  // n. steps y
int zpos = 110; // n. steps z
int rpos = 90;  // n. rot steps

int maxpx = 175;  // max steps x
int maxpy = 175;  // max steps y
int maxpz = 175; // max steps z
int maxpr = 175;  // max rot step

int minpx = 30;  // max steps x
int minpy = 30;  // max steps y
int minpz = 110; // max steps z
int minpr = 30;  // max rot step

// Set up variables

int buttonState = 0;

int mapX = 0;
int mapY = 0;
int map2X = 0;
int map2Y = 0;

int shutter = 1;        // flag to activate/disactivate the bluetooth remote control
int initial_position = 90;


// setup the servo object name for the blade movement
Servo servo ; // servo for pressing the bluetooth remote control
Servo servo1 ; // servo for controlling the focus of the microscope
Servo servo2 ; // servo for pressing mouse button
Servo servo3 ; // servo for controlling the focus of the microscope
Servo servo4 ; // servo for pressing mouse button


// initialize the library with the numbers of the interface pins
LiquidCrystal_I2C lcd(I2C_ADDRESS, LCD_CHAR, LCD_LINE);


void setup() {
  Serial.begin(9600);


  pinMode(XJOY1_PIN, INPUT);
  pinMode(YJOY1_PIN, INPUT);
  pinMode(BUTJOY1_PIN, INPUT_PULLUP);
  pinMode(XJOY2_PIN, INPUT);
  pinMode(YJOY2_PIN, INPUT);
  //  pinMode(BUTJOY2_PIN, INPUT_PULLUP);

  servo.attach(12);
  servo1.attach(5); // X-movment
  servo2.attach(6); // Y-movment
  servo3.attach(7); // Z-movment
  servo4.attach(8); // Rotation

  servo1.write (initial_position);
  servo2.write (initial_position);
  servo3.write (initial_position);
  servo4.write (initial_position);

  lcd.init();
  lcd.backlight();
  lcd.print(TITLE_LCD[0]);
  lcd.setCursor(0, 1);
  lcd.print(TITLE_LCD[1]);
  delay(2000);
  lcd.print(TITLE_LCD[2]);
}

void loop() {

  /*
      JOYSTICK MODULE CONTROL
  */

  // Read the joystick button state
  buttonState = digitalRead(BUTJOY1_PIN);

  if (!buttonState) ShutterControl();

  // Read analog value from Joystick 1

  int joystickXVal = analogRead(XJOY1_PIN) ;
  int joystickYVal = analogRead(YJOY1_PIN) ;
  mapX = map(joystickXVal, 0, 1023, -512, 512);
  mapY = map(joystickYVal, 0, 1023, -512, 512);

  if (  mapX <=  -250 )
  {
    MoveXYZ(1);
  } else if  (mapX >= 250) {
    MoveXYZ(-1);
  }

  if (  mapY <= -250 )
  {
    MoveXYZ(2);
  } else if (mapY > 250 ) {
    MoveXYZ(-2);
  }
  
  //
  //  Read analog value from Joystick 2
  //

  int joystickRVal = analogRead(XJOY2_PIN) ;
  int joystickZVal = analogRead(YJOY2_PIN) ;
  map2X = map(joystickRVal, 0, 1023, -512, 512);
  map2Y = map(joystickZVal, 0, 1023, -512, 512);

  if (  map2Y <=  -250 )
  {
    RotateDown();
  } else if  (map2Y >=  250) {
    RotateUp();
  }

  //
  if (  map2X <=  -250 )
  {
    MoveXYZ(3);
  } else if  (map2X >=  250) {
    MoveXYZ(-3);
  }

  delay (100) ;

}

/*
 **** FUNCTIONS ****
*/

// Rotation of the microscope slide
void  RotateDown() {
  if (rpos < minpr) {
    rpos = minpr;
  } else {
    rpos = rpos - rstep;
    servo4.write ( rpos ) ;
  }
  printSteps();
  delay (100) ;
}

void  RotateUp() {
  if (rpos > maxpr) {
    rpos = maxpr;
  } else {
    rpos = rpos + rstep;
    servo4.write ( rpos ) ;
  }
  printSteps();
  delay (100) ;
}

// XYZ translation of the microscope slide

void MoveXYZ(int dir)
{
  if (dir == 1) {
    if (xpos < minpx) {
      xpos = minpx;
    } else {
      xpos = xpos - tstep;
      servo1.write ( xpos ) ;
    }
  }
  if (dir == -1) {
    if (xpos > maxpx) {
      xpos = maxpx;
    } else {
      xpos = xpos + tstep;
      servo1.write ( xpos ) ;
    }
  }
  if (dir == 2) {
    if (ypos < minpy) {
      ypos = minpy;
    } else {
      ypos = ypos - tstep;
      servo2.write ( ypos ) ;
    }
  }
  if (dir == -2) {
    if (ypos > maxpy) {
      ypos = maxpy;
    } else {
      ypos = ypos + tstep;
      servo2.write ( ypos ) ;
    }
  }
  if (dir == 3) {
    if (zpos < minpz) {
      zpos = minpz;
    } else {
      zpos = zpos - tstep;
      servo3.write ( zpos ) ;
    }
  }
  if (dir == -3) {
    if (zpos > maxpy) {
      zpos = maxpy;
    } else {
      zpos = zpos + tstep;
      servo3.write ( zpos ) ;
    }
  }
  printSteps();
  delay (100) ;
}

// Print steps on the LCD

void printSteps() {

  clearLine1();
  clearLine2();
  lcd.setCursor(0, 0);
  lcd.print("X:");
  lcd.print(xpos);
  lcd.print(" Y: ");
  lcd.print(ypos);

  lcd.setCursor(0, 1);
  lcd.print("Z:");
  lcd.print(zpos);
  lcd.print(" ROT: ");
  lcd.print(rpos);
}


// Press the button on the bluetooth remote control

void ShutterControl() {

  delay(500);
  servo.write(25);
  delay(500);
  servo.write(75);
  delay(1000);

}

// LCD lines clean functions

void clearLine1()
{
  for (int i = 0; i <= LCD_CHAR - 1; i++)
  {
    lcd.setCursor (i, 0);
    lcd.write(254);
  }
}

void clearLine2()
{
  for (int i = 0; i <= LCD_CHAR - 1; i++)
  {
    lcd.setCursor (i, 1); //
    lcd.write(254);
  }
}


Step 6: Action!

The first animated GIF-file shows the rotation and Z-translation motion operated using the left joystick. The second video shows the movement along the device's X and Y axis, controlled by the joystick module on the left. By pressing down the left joystick module, the Servo5 is activated pressing the Bluetooth remote button (shown in the third video). 

Step 7: Conclusions

We have presented a prototype for a four-axis translation and rotation robotic device that can be used to position a slide under a stereo or USB microscope. The device is made modular to use for different purposes. For example, removing the Y-stage should be sufficient to fit it under a stereomicroscope (see Figure). Although the electronic interface is quite bulky, the device is simple to assemble and use, and the controlling program is still in its early stages. The ultimate goal is to use it for automatic photo stacking (see videos) or 3D image reconstruction. Still, we are sure there are other possible applications in which small motion in 3D dimensions and a rotation of the observation stage can be helpful.


This is a prototype, and there is a lot of space for improvements. So we hope you like it, and constructive comments and suggestions are always welcome!