//============================================================================= //============================================================================= // // Routines to run the XOS X-Beam Filter Wheel under Windows. Requires the GiveIo // device to be installed which allows port I/O access with _inp() and _outp(), // and thus requires NT, 2000, or XP. GiveIo is not required for Windows 3.1, 95, // or ME. The GiveIo service can be downloaded as GiveIoNT2000XP.zip from // www.aethermachines.com under Software and Downloads. // // Copyright (c) 2005 AetherMachines Inc. This software may be freely modified // and distributed by the end user provided AetherMachines Inc. is cited as the // source of the original code. For instance : // // 0.0.0 Derived from AetherMachines original source // 1.0.0 Added feature A // 2.0.0 Added feature B // // or // // "The following AetherMachines Inc. code is provided free of charge" // // Revisions : // ---------------------------------------------------------------------------- // // 0.0.0 MDM Initial 9/7/05. // 1.0.0 Changed DB-25 pin assignments as per XOS/Seiko 10/27/05 MDM. // 1.1.0 Added dither in test steps to avoid finding the Home Sensor // just before moving in the opposite direction 12/12/05 MDM. // 1.2.0 Made the step calculation floating point instead of integer 1/9/05 MDM. // //============================================================================= //============================================================================= #include #include #include #include #include #define PARALLEL_PORT_WRITE 0x378 #define PARALLEL_PORT_READ 0x379 //***************************************************************************** // New pin definitions ... // // 98765432 PARALLEL PORT PINS // 76543210 PARALLEL PORT BITS // 00000000 CW_FALLING_EDGE // 00000010 CW_RISING_EDGE // 00000100 CCW_FALLING_EDGE // 00000110 CCW_RISING_EDGE // 00001110 INHIBIT_MOTOR #define CCW_FALLING_EDGE 4 #define CCW_RISING_EDGE 6 #define CW_FALLING_EDGE 0 #define CW_RISING_EDGE 2 #define MAX_FILTER_NUMBER 8 #define FILTER_STEP_CONSTANT 29.143 #define INHIBIT_MOTOR 14 //***************************************************************************** //***************************************************************************** // // InhibitMotor() turns off all phases of the stepper with the INH pin. // Holding torque is then just whatever mechanical torque exists intrinsically // in the motor; no magnetic flux is generated. // // // Copyright (c) 2005 AetherMachines Inc. This software may be freely modified // and distributed by the end user provided AetherMachines Inc. is cited as the // source of the original code. For instance : // // 0.0.0 Derived from AetherMachines original source // 1.0.0 Added feature A // 2.0.0 Added feature B // // or // // "The following AetherMachines Inc. code is provided free of charge" // // Revisions : // ---------------------------------------------------------------------------- // // 0.0.0 MDM Initial 9/7/05. // //***************************************************************************** //***************************************************************************** void InhibitMotor(void) { _outp(PARALLEL_PORT_WRITE, INHIBIT_MOTOR); } //***************************************************************************** //***************************************************************************** //***************************************************************************** //***************************************************************************** // // StepCCW() takes a counter clockwise step when looking down at the filter wheel // assembly. The negative going /STEP pulse is held high for 10ms and then // transitions low. PulseWait milliseconds are waited before the next step // of multiple steps or before a single step call to StepCCW() returns. // // // Copyright (c) 2005 AetherMachines Inc. This software may be freely modified // and distributed by the end user provided AetherMachines Inc. is cited as the // source of the original code. For instance : // // 0.0.0 Derived from AetherMachines original source // 1.0.0 Added feature A // 2.0.0 Added feature B // // or // // "The following AetherMachines Inc. code is provided free of charge" // // Revisions : // ---------------------------------------------------------------------------- // // 0.0.0 MDM Initial 9/7/05. // //***************************************************************************** //***************************************************************************** void StepCCW(int NumberOfSteps, int PulseWait) { int i; for (i = 0; i < NumberOfSteps; i++) { _outp(PARALLEL_PORT_WRITE, CCW_RISING_EDGE); Sleep(10); _outp(PARALLEL_PORT_WRITE, CCW_FALLING_EDGE); Sleep(PulseWait); } } //***************************************************************************** //***************************************************************************** //***************************************************************************** //***************************************************************************** // // StepCW() takes a clockwise step when looking down at the filter wheel // assembly. The negative going /STEP pulse is held high for 10ms and then // transitions low. PulseWait milliseconds are waited before the next step // of multiple steps or before a single step call to StepCW() returns. // // // Copyright (c) 2005 AetherMachines Inc. This software may be freely modified // and distributed by the end user provided AetherMachines Inc. is cited as the // source of the original code. For instance : // // 0.0.0 Derived from AetherMachines original source // 1.0.0 Added feature A // 2.0.0 Added feature B // // or // // "The following AetherMachines Inc. code is provided free of charge" // // Revisions : // ---------------------------------------------------------------------------- // // 0.0.0 MDM Initial 9/7/05. // //***************************************************************************** //***************************************************************************** void StepCW(int NumberOfSteps, int PulseWait) { int i; for (i = 0; i < NumberOfSteps; i++) { _outp(PARALLEL_PORT_WRITE, CW_RISING_EDGE); Sleep(10); _outp(PARALLEL_PORT_WRITE, CW_FALLING_EDGE); Sleep(PulseWait); } } //***************************************************************************** //***************************************************************************** //***************************************************************************** //***************************************************************************** // // ReadHomeSensor() returns whether the Home Mark is currently under the Home // Sensor (0 not visible, 1 visible). The Home Mark is typically visible for // 1-3 7.5 degree steps. // // Copyright (c) 2005 AetherMachines Inc. This software may be freely modified // and distributed by the end user provided AetherMachines Inc. is cited as the // source of the original code. For instance : // // 0.0.0 Derived from AetherMachines original source // 1.0.0 Added feature A // 2.0.0 Added feature B // // or // // "The following AetherMachines Inc. code is provided free of charge" // // Revisions : // ---------------------------------------------------------------------------- // // 0.0.0 MDM Initial 9/7/05. // //***************************************************************************** //***************************************************************************** int ReadHomeSensor(void) { return((_inp(PARALLEL_PORT_READ) & 0x08) >> 3); } //***************************************************************************** //***************************************************************************** //***************************************************************************** //***************************************************************************** // // FindHome() steps the Filter Wheel CCW until it finds and passes over the // Home Mark. Stepping decelerates over the Home Mark and 1/2 of the width of // the Home Mark is stepped in the opposite directio to locate the exact center // of the Home Mark. If the Home Mark appears too long or short, three tries // of backing up and resensing are allowed, at which point a failure is declared. // // // Copyright (c) 2005 AetherMachines Inc. This software may be freely modified // and distributed by the end user provided AetherMachines Inc. is cited as the // source of the original code. For instance : // // 0.0.0 Derived from AetherMachines original source // 1.0.0 Added feature A // 2.0.0 Added feature B // // or // // "The following AetherMachines Inc. code is provided free of charge" // // Revisions : // ---------------------------------------------------------------------------- // // 0.0.0 MDM Initial 9/7/05. // //***************************************************************************** //***************************************************************************** int FindHome(void) { #define FILTER_OFFSET 0 int HomeSensor; int HomeCounts; int Steps; int FindMiddle; int FindTries; HomeSensor = 0; Steps = 0; FindTries = 0; //***************************************************************************** // Dither the wheel CCW away from the home sensor ... StepCCW(10,10); ReFind: HomeCounts = 0; Steps = 0; //***************************************************************************** // Search for a string of home sensor detections ... do { StepCCW(1, 10); HomeSensor = ReadHomeSensor(); Steps++; } while (HomeSensor == 0 && Steps < 250); HomeSensor = ReadHomeSensor(); HomeCounts = HomeCounts + HomeSensor; Steps = 0; do { StepCCW(1, 100); HomeSensor = ReadHomeSensor(); HomeCounts = HomeCounts + HomeSensor; Steps++; } while (HomeSensor == 1 && Steps < 250); //***************************************************************************** // Wait a bit for any 'intertia' effects and prepare for a falling edge ... Sleep(500); _outp(PARALLEL_PORT_WRITE, CW_RISING_EDGE); //***************************************************************************** // Return CW to the center of the Home Mark plus an offset (if desired) ... FindMiddle = HomeCounts / 2; if (FindMiddle == 0) { FindMiddle++; } for (Steps = 0; Steps < (FindMiddle + FILTER_OFFSET); Steps++) { StepCW(1, 100); } //***************************************************************************** // Error/refind conditions are currently a glitch or abnormal prolonged detection ... if (FindTries > 2) { printf("FindHome() failed ...\r\n"); return(FindTries); } //printf("H->%d\r\n", HomeCounts); if (HomeCounts < 1 || HomeCounts > 5 && FindTries < 3) { for (Steps = 0; Steps < 10; Steps++) { StepCW(1, 100); } FindTries++; goto ReFind; } return(FindTries); } //***************************************************************************** //***************************************************************************** //***************************************************************************** //***************************************************************************** // // InsertFilter() finds the Home Mark and then rotates to the desired filter, // specified via an integer 1 <= i <= 8. // // Copyright (c) 2005 AetherMachines Inc. This software may be freely modified // and distributed by the end user provided AetherMachines Inc. is cited as the // source of the original code. For instance : // // 0.0.0 Derived from AetherMachines original source // 1.0.0 Added feature A // 2.0.0 Added feature B // // or // // "The following AetherMachines Inc. code is provided free of charge" // // Revisions : // ---------------------------------------------------------------------------- // // 0.0.0 MDM Initial 9/7/05. // //***************************************************************************** //***************************************************************************** int InsertFilter(int FilterNumber) { #define INSERT_FILTER_OFFSET 0 int FindHomeRetries; double NumberOfSteps; FindHomeRetries = 0; //***************************************************************************** // Check for valid filter ... if (FilterNumber > 0 && FilterNumber <= MAX_FILTER_NUMBER) { FindHomeRetries = FindHome(); Sleep(500); if (FindHomeRetries < 2) { NumberOfSteps = (((FilterNumber - 1) * FILTER_STEP_CONSTANT) + INSERT_FILTER_OFFSET); printf("@%f\r\n", NumberOfSteps); StepCCW((int) NumberOfSteps, 10); } } else { FindHomeRetries = -1; } return(FindHomeRetries); } //***************************************************************************** //***************************************************************************** //***************************************************************************** //***************************************************************************** // // TestFilterWheel() flashes LEDs 1-3 5 times each, rotates CCW and CW to pick // up the Home Mark, and finally performs the initial FindHome() call. // // Copyright (c) 2005 AetherMachines Inc. This software may be freely modified // and distributed by the end user provided AetherMachines Inc. is cited as the // source of the original code. For instance : // // 0.0.0 Derived from AetherMachines original source // 1.0.0 Added feature A // 2.0.0 Added feature B // // or // // "The following AetherMachines Inc. code is provided free of charge" // // Revisions : // ---------------------------------------------------------------------------- // // 0.0.0 MDM Initial 9/7/05. // 1.0.0 Added dither of ten steps away in the other direction when testing // CW and CCW 12/12/05 MDM. // //***************************************************************************** //***************************************************************************** int TestFilterWheel(void) { int i; int Steps; int FindHomeTries; Steps = 0; FindHomeTries = 0; //***************************************************************************** // Print a basic banner ... printf("*******************************************************************************\r\n"); printf("FilterWheel.exe v1.2.0 Copyright (c) 2005 AetherMachines Inc.\r\n\r\n\r\n"); printf(" ***** TESTING FILTER WHEEL *****\r\n\r\n"); //***************************************************************************** // Turn off all LEDs ... _outp(PARALLEL_PORT_WRITE, 7); Sleep(500); //***************************************************************************** // Flash LED 1 (/STEP) ... for (i = 0; i < 5; i++) { _outp(PARALLEL_PORT_WRITE, 12); Sleep(250); printf("."); _outp(PARALLEL_PORT_WRITE, 14); Sleep(250); } printf("\r\n"); //***************************************************************************** // Flash LED 2 (DIRECTION) ... for (i = 0; i < 5; i++) { _outp(PARALLEL_PORT_WRITE, 10); Sleep(250); printf("."); _outp(PARALLEL_PORT_WRITE, 14); Sleep(250); } printf("\r\n"); //***************************************************************************** // Flash LED 3 (INHIBIT) ... for (i = 0; i < 5; i++) { _outp(PARALLEL_PORT_WRITE, 6); Sleep(250); printf("."); _outp(PARALLEL_PORT_WRITE, 14); Sleep(250); } printf("\r\n"); //***************************************************************************** // Rotate until the Home Mark is found ... StepCCW(10,10); do { StepCCW(1,10); Steps++; } while (Steps < 260 && ReadHomeSensor() == 0); if (Steps > 250) { printf("CCW seek problem ...\r\n"); } else { printf(".\r\n"); } Steps = 0; Sleep(1000); //***************************************************************************** // Rotate until the Home Mark is found ... StepCW(10,10); do { StepCW(1,10); Steps++; } while (Steps < 260 && ReadHomeSensor() == 0); if (Steps > 250) { printf("CW seek problem ...\r\n"); } else { printf(".\r\n"); } Sleep(1000); //***************************************************************************** // Find Home and print user instructions ... FindHomeTries = FindHome(); if (FindHomeTries < 2) { printf("\r\nOK ...\r\n"); printf("\r\nEnter 1,2, ... 8 for desired filter\r\n"); printf("Enter l/L for low power hold\r\n"); } printf("\r\n\r\n\r\n"); return(FindHomeTries); } //***************************************************************************** //***************************************************************************** //============================================================================= //============================================================================= // // main() attaches to the GiveIo device (service), runs TestFilterWheel() and // enters the main loop where the user specifies which filters to use. // // Copyright (c) 2005 AetherMachines Inc. This software may be freely modified // and distributed by the end user provided AetherMachines Inc. is cited as the // source of the original code. For instance : // // 0.0.0 Derived from AetherMachines original source // 1.0.0 Added feature A // 2.0.0 Added feature B // // or // // "The following AetherMachines Inc. code is provided free of charge" // // Revisions : // ---------------------------------------------------------------------------- // // 0.0.0 MDM Initial 9/7/05. // //============================================================================= //============================================================================= int main() { int ch; HANDLE hGiveIo; //***************************************************************************** // Attach to the GiveIo device ... hGiveIo = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hGiveIo == INVALID_HANDLE_VALUE) { printf("GiveIo device unavailable ...\r\n"); return -1; } CloseHandle(hGiveIo); //***************************************************************************** // Test Filter Wheel operation ... TestFilterWheel(); //***************************************************************************** // Enter the main loop ... do { printf("FilterWheel-> "); ch = toupper(getche()); printf("\r\n"); if (ch == 'l' || ch == 'L') { InhibitMotor(); } else { InsertFilter(ch - 48); } } while(1); return (0); } //============================================================================= //=============================================================================