/***************************************************************************** * * Camera Panning Control V1.0. * * compile with: gcc -O campan.c -o campan * * campan is a simple program to interface with Garry Ellard's PIC Stepper * Motor Circuit. This version uses the modem control lines on ttys0 to pan * a webcam left or right and will indicate when end stop switches are * activated. * * Modem control lines: DTR - direction Left +12V Right -12V (pin 4) * RTS - move Move +12V Stop -12V (pin 7) * CTS - left stop ~Lstop +12V Lstop -12V (pin 8) * DSR - right stop ~Rstop +12V Rstop -12V (pin 6) * Gnd - signal ground 0V (pin 5) * * Archie Howitt 4 April 2003 * * reference: * http://www.easysw.com/~mike/serial/serial.html * http://www.geocities.com/SiliconValley/Park/4572/tips.html * http://docsrv.caldera.com:8457/en/SerialProg/Serial-Programming-HOWTO.html * *****************************************************************************/ #include // Standard input/output definitions #include // String function definitions #include // UNIX standard function definitions #include // File control definitions #include // Error number definitions //#include // POSIX terminal control definitions #include // terminal control definitions #define left TIOCM_DTR; // pan direction left - DTR +12V (space) #define right ~TIOCM_DTR; // pan direction right - DTR -12V (mark) #define stop TIOCM_RTS; // stop panning - RTS +12V (space) #define move ~TIOCM_RTS; // pan - RTS -12V (mark) struct termios options; // TERMIOS structure for local port int fd; // File Descriptor for the port int status; // port status store /********************************************* * 'open_port()' - Open serial port 1. * * Returns the Port file descriptor on success or -1 on error. * */ int open_port(void) { fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { // Could not open the port. perror("open_port: Unable to open /dev/ttyf1 - "); } else { fcntl(fd, F_SETFL, 0); // clear the port flags } return (fd); } /******************************************** * 'getch()' - get character from keyboard. * */ int getch() { int c, i, fd=0; struct termios term, oterm; tcgetattr(fd, &oterm); // get the terminal settings memcpy(&term, &oterm, sizeof(term)); // make a copy of the settings term.c_lflag = term.c_lflag & (!ICANON); // terminal in non-canonical mode term.c_cc[VMIN] = 1; // set - read one character term.c_cc[VTIME] = 0; // set - return immediately tcsetattr(fd, TCSANOW, &term); // set terminal to this c=getchar(); // get a character tcsetattr(fd, TCSANOW, &oterm); // reset the terminal to its original state return c; // return the charcter } /******************************************* * 'stepmove ()' - pulse the stepper motor * * entry - direction character 'l' or 'r' * return - number of step pulses moved * * left end stop switch on modem control line CTS * right end stop switch on modem control line DSR * */ int stepmove (char direction) { int t1, t2, pstep, s; int pcount = 0; // number of step pulses moved int endstop = 0; // pan end stop indicator printf("Enter number of pan steps: "); s = scanf("%d", &pstep); // get the number of pan steps if(s==0){ // did scanf() format fail? printf("Input must be a number!\n"); // ouch! numbers only getch(); // clear the keyboard buffer getch(); // twice ?? OK it works return pcount; } getch(); // always clear the keyboard buffer // after scanf() // now pan number of step pulses checking the end stop switches each time while((pcount < pstep) && !(endstop)) { ioctl(fd, TIOCMGET, &status); // get the port status if(!(status & TIOCM_CTS) && (direction == 'l')) { // hit left stop? endstop++; // yes printf("We've hit Left stop!!!\n"); } if(!(status & TIOCM_DSR) && (direction =='r')) { // hit right stop? endstop++; //yes printf("We've hit Right stop!!!\n"); } if(endstop) // did we hit an end stop? break; // if so end out status &= move; // no we didn't hit an end stop so pulse move ioctl(fd, TIOCMSET, &status); for(t1=0; t1<9999; t1++) { for (t2=0; t2<999; t2++); } ioctl(fd, TIOCMGET, &status); status |= stop; ioctl(fd, TIOCMSET, &status); for(t1=0; t1<9999; t1++) { for (t2=0; t2<999; t2++); } pcount++; // bump pulse counter //printf("Number of pulses = %d\n", pcount); } return pcount; } /*************************************************** * 'pancommand()' get direction command 'l' - Left * 'r' - Right * 'q' - quit * * direction indicated by modem control line DTR - left DTR +12V (space) * - right DTR -12V (mark) * return - command 'l', 'r' or 'q' */ int pancommand (void) { char c; // command int numstep; // returned step counts printf("Enter Command (l, r or q): "); c = getch(); printf("%c\n",c); switch (c){ case 'l': // left ioctl(fd, TIOCMGET, &status); status |= left; ioctl(fd, TIOCMSET, &status); printf("Direction set as: LEFT (DTR +12V - space)\n"); numstep = stepmove(c); break; case 'r': // right ioctl(fd, TIOCMGET, &status); status &= right; ioctl(fd, TIOCMSET, &status); printf("Direction set as: RIGHT (DTR -12V - mark)\n"); numstep = stepmove(c); break; case 'q': numstep = 0; break; default: printf("Command: %c - not supported. Enter l for Left r for Right q to quit.\n", c); } if((c == 'l') || (c == 'r')) printf("Number of step pulses actually moved = %d\n", numstep); return c; } /************************************************ * 'main ()' * */ main () { char quit=0; open_port (); // open serial port and get file descriptor printf("Start program - RTS & DTR +12V (space)\n"); while(quit != 'q'){ quit = pancommand(); // request command - 'q' quits program } close (fd); // close port }