-
Arduino Code
04/21/2015 at 20:13 • 0 comments//parts of this code have been scavenged from code created by: Michael Pilcher #include <AFMotor.h> //manually calibrate your stage to find the values of xmove and y move for each objective you will be using int xmove = 12;//[12 (100x) 30 (40x) dp72] int ymove = 5;//[5 (100x) 13 (40x) dp72] int xrpm = 150; int yrpm = 150; int j = 1; // integer used in scanning the array designating column number //2-dimensional array for assigning the buttons and there high and low values int Button[9][3] = {{1, 705, 715}, // button 1 {2, 735, 745}, // button 1b {3, 830, 840}, // button 2 {4, 845, 860}, // button 2b {5, 600, 620}, // button 3 {6, 640, 670}, // button 3b {7, 300, 320}, // button 4 {8, 445, 460}, // button 4b {9, 260, 265}, // button b }; int analogpin = 0; // analog pin to read the buttons int label = 0; // setting button mode int counter = 0; // how many times we have seen new value long time = 0; // the last time the output pin was sampled int debounce_count = 50; // number of millis/samples to consider before declaring a debounced input int current_state = 0; // the debounced input value int ButtonVal; int column=8; int row=50; int row_count; int column_count; double movement; int pause = 2800; int frames=0; int count = 0; AF_Stepper motor1(100, 1); AF_Stepper motor2(100, 2); void setup() { Serial.begin(9600); motor1.setSpeed(yrpm); motor2.setSpeed(xrpm); } void loop() { // If we have gone on to the next millisecond if (millis() != time) { // check analog pin for the button value and save it to ButtonVal ButtonVal = analogRead(analogpin); if(ButtonVal == current_state && counter >0) { counter--; } if(ButtonVal != current_state) { counter++; } // If ButtonVal has shown the same value for long enough let's switch it if (counter >= debounce_count) { counter = 0; current_state = ButtonVal; //Checks which button or button combo has been pressed if (ButtonVal > 0) { ButtonCheck(); } } time = millis(); } } void ButtonCheck() { // loop for scanning the button array. for(int i = 0; i <= 21; i++) { // checks the ButtonVal against the high and low vales in the array if(ButtonVal >= Button[i][j] && ButtonVal <= Button[i][j+1]) { // stores the button number to a variable label = Button[i][0]; Action(); } } } void Action() { if(label == 1) { Serial.println("Button 1");//Y Coordinate down motor1.step(xmove, FORWARD, DOUBLE); } if(label == 2) { Serial.println("Column ="); column++; Serial.println(column); } if(label == 3) { Serial.println("Button 2"); //Y Coordinate up motor1.step(xmove, BACKWARD, DOUBLE); } if(label == 4) { Serial.println("Initiated"); row_count=1; movement=1; column_count=1; frames= row * column; while(count<= frames){ if( movement==1){ while(column_count <= column){ motor1.step(xmove, FORWARD, DOUBLE); Serial.println(column_count); Serial.println(movement); delay(pause); count++; column_count++; } } if( movement!= 1){ while(column_count >= 1){ motor1.step(xmove, BACKWARD, DOUBLE); Serial.println(column_count); Serial.println(movement); delay(pause); count++; column_count--; } } if (column_count==column+1){ if(movement == 1){ motor2.step(ymove, BACKWARD, DOUBLE); Serial.println(column_count); Serial.println(movement); delay(pause); count++; column_count = column; movement = movement * (-1); row_count++; motor1.step(xmove-2, BACKWARD, DOUBLE); Serial.println(column_count); Serial.println(movement); delay(pause); count++; column_count--; } } if (column_count == 0){ if(movement ==- 1){ motor2.step(ymove, BACKWARD, DOUBLE); Serial.println(column_count); Serial.println(movement); delay(pause); count++; column_count =1 ; row_count++; movement=1; } } } } if(label == 5) { Serial.println("Button 3"); //x coordinate to the left motor2.step(ymove, FORWARD, DOUBLE); } if(label == 6) { Serial.println("Row ="); row++; Serial.println(row); } if(label == 7) { Serial.println("Button 4"); //x coordinate to the right motor2.step(ymove, BACKWARD, DOUBLE); } if(label == 8) { Serial.println("reset"); } if(label == 9) { Serial.println("switch"); } }
-
Example Montage and Status
04/21/2015 at 20:07 • 0 commentsThanks for all the interest, and I apologize for the lack of updates and responses over the last year (my dissertation research got in the way). I neglected to document Stagmo as much as I should have during my graduate research, but I have uploaded an example montage (undecalficied human midshaft femur thick-section – 100~µm thick). The size of this montage was greatly reduced for internet viewing and is made up of 180 individual fields. This demonstrates the ability and weaknesses of Stagmo coupled with an imageJ stitching plugin. The software end is highly sensitive to "blank" fields, so fields with minimal features are more likely to be misaligned (as seen the medullary cavity). Since these fields typically do not have features of interest, this wasnt a big deal for my research and could be fixed in photoediting software using the raw images after stitching for the small number of montages that were problematic.
Stagmo is currently on hold, but I am happy to revive and update this project with interested individuals. There are a number of improvements that can easily be made. The first edition was significantly hindered by limited tools and materials. Future updates could include a significantly improved UI, computer triggering and interface, and the addition of automated focus control (using a simple plane capturing method). Since stagmo is design to attach to existing stages (which are typically precisely machined and expensive), the general concept should not be restricted to any specific microscope. 3D printed hubs coupled with standard hardware could provide a range of automated options to low budget researchers.