My setup is like this:-
Webcam connected to Computer Via USB lead, mounted on top of Microscope.
Stepper Moter connected to computer via Serial lead, and to Microscope fine focus knob by rubber tubing.
CombineZM running on computer controlling both Camera and Microscope focus.
Small Program sits between CZM and Motor.
Here is how I set CombineZM up:-
First tell CZM which camera to use File Menu->Acquire Images->Select Source, choose a Video source.
Now edit External Commands 11 and 12 Macro Menu->Edit->Commands choose External Command 11 and fill it in something like this:-
Name Down
Program Stepper
Command Line x -100 600 0
This command will move the microscope stage down hence the Name of the command. 'Stepper' is the name of a small program that controls my motor, it resides in the same folder as CZM. The last line will be passed to this program which in turn will use it as an instruction to control the motor. In this case 'X' could be any single word, it's ignored by my program (it could be used to pass an instruction to a more sophisticated program). The first number is the number of stepper motor steps, -ve numbers move my stage down, and +ve up. The second number is how fast to run the motor, steps per second. The third number is not used.
Now click OK, and edit External Command 12 in the same way, only this time enter 100 in place of -100 to make the stage go the other way. OK again then close the Choose Command box.
Now we can test it. Press F5, or click View Menu->Toggle Video (which you may have noticed is also on the Acquire Image sub menu of the File Menu). The main window of CombineZM should now be filled with a moving picture down your microscope. Use the course focus knob to bring something into focus. Now test the two commands just entered by pressing F11 or F12, your motor should come to life and turn the fine focus knob of your scope, the consequences should be visible on the screen. F5 will turn the video off.
Note when you save a Macro Set the associated commands will be saved as well, so you could have a Low Power set as above and a High Power set with 100 changed for say 10.
First of all, to create a new Macro Set, click on Macro Menu->Clear All Macros,
The second job is to create another External Command
Name Stepper
Program Stepper
Command Line x
This is done in just the same way as the ones above. Notice the lack of numbers after the 'x', this command will be used from within a macro and will have three numbers added to it see below.
Now we will write instructions that will set a timer, take a picture, move the microscope stage and wait for the timer to expire. By splitting the timer function into two parts like this you get a more even time interval, useful for timelapse photography. In this application the timer is necessary because it takes time for a camera to take a picture and then to send it back to the computer, if commands to take pictures come two quickly something will give and the process will come to a grinding halt. I am afraid this time interval must be found by trial and error, remember to allow time for the stepper motor to do it's work and the camera it's.
We will take ten pictures, to do this the above sequence will be repeated 10 times. To do this write two macros, the first will start the second 10 times. First click Macro Menu->Edit Macros, now choose to edit the first macro, and fill it's name in "Take 10 Pictures" and immediately click OK. Repeat the last step for the second Macro only enter "Take 1 Picture". Go back and edit the first Macro again, Drop the command list down and notice our two Macro's names appear in the list. This first Macro only consists of two lines, choose the first from the dropdown list.
Take 1 Picture
and fill in the three numbers underneath it as 1 1 10, make sure the top line of the main macro editor window is highlighted and press Update, the information you just entered will be reproduced on the top line in the format "Take 1 Picture(1,1,10)". The numbers in brackets are the numbers you entered.
Interpret this line like this, start counting from 1, do the Take 1 Picture macro, add 1 to the count, if it is greater than 10 finish this line, otherwise take another picture and increase the count again and do the test again and again and again until the count is greater than 10.
Now select the line
Goto Top Frame
from the dropdown list and make sure the second line of the Macro window is highlighted before pressing Update. This line is optional but it makes sure that when we finish the last picture taken is visible. The window should show these two lines:-
Take 1 Picture(1,1,10)
GotoTop Frame
That's the first Macro finished, just click OK. The second Macro is entered in exactly the same way and should look like this when finished.
Start Seconds Timer(1)
Take a Picture
Stepper(-100,200,0)
Wait for Timeout
We are going to take pictures 1 per second. The stepper motor will move down 100 units after each picture is taken. Notice this macro uses the command called Stepper which was created above and it's name has been added to the Macro Commands dropdown list. You may be wondering why I used -100, the answer is so that the microscope stage moves down and no damage to slides will occur if I made a mistake.
Before trying the Macro Set save it using Macro Menu->Save Macro Set As.
To use this set you must choose a video device, or a video and a still device, by using the File Menu->Acquire Images->Choose Source menu item. Then choose a place to save your stack, and clear any old stack by clicking on New Stack which is on the same submenu.
Now click on Macro Menu->Take 10 Pictures, hey presto, thus mote it be.
Finally for the programmers out there here is the C++ code I use to drive my motor.
#include
"stdafx.h"
// you need next line so timer functions will compile
#define
_WIN32_WINNT 0x0400
#include
"windows.h"
#include
"stdio.h"
HANDLE timer=0;
// 64 bit arithmetic for timers, resolution 100ns
void StartTimer(__int64
mseconds)
{
// dispose of any old
timer
if(timer)
CloseHandle(timer); timer=0;
timer=CreateWaitableTimer(0,false,"StepperTimer");
LARGE_INTEGER due;
// convert ms to 100ns
due.QuadPart=-10000L*mseconds;
SetWaitableTimer(timer,&due,0,0,0,false);
}
void
WaitForTimer()
{
WaitForSingleObject(timer,INFINITE);
if(timer)
CloseHandle(timer);
timer=0;
}
// args 0=prog, 1=command, 2=steps,
3=speed, 4=don't care
int _tmain(int
argc, _TCHAR* argv[])
{
if(argc!=5)
return -1;
// use serial port to communicate with
stepper motor controller
DCB dcb;
HANDLE f=CreateFile(
"COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
// get current port settings
GetCommState(f,&dcb);
// change to suit motor controller
dcb.BaudRate=CBR_19200;
dcb.ByteSize=8;
dcb.Parity=NOPARITY;
dcb.StopBits=ONESTOPBIT;
SetCommState(f,&dcb);
/ / convert params to long ints
int i;
__int64
steps=0; i=(argv[2][0]=='-')?1:0;
while(argv[2][i]){steps=steps*10+(argv[2][i]-'0');
i++;};
__int64
speed=0; i=(argv[3][0]=='-')?1:0;
while(argv[3][i]){speed=speed*10+(argv[3][i]-'0');
i++;};
//
calculate ms, allow 200 extra, start timer
StartTimer((steps*1000L+500L)/speed+200);
// send command to moter
char* command[1024];
DWORD n; // number of bytes sent, useless
to me
sprintf((char*)command,"{IE%s,%s,%s,5,0,0}",argv[2],argv[3],argv[3]);
WriteFile(f,(char*)command,(DWORD)strlen((char*)command),&n,0);
FlushFileBuffers(f);
// close serial port
CloseHandle(f);
// finish waiting till time's up
WaitForTimer();
return 0;
}