head 4.4; access ; symbols ; locks oasisa:4.4; strict; comment @ * @; 4.4 date 2001.06.19.12.15.27; author oasisa; state Exp; branches ; next ; desc @New Repository; 6/19/2001 (klh) @ 4.4 log @New Repository; 6/19/2001 (klh) @ text @/****************************************************************************/ /* Copyright 1997 MBARI */ /****************************************************************************/ /* $Header: shut22.c,v 1.1 2001/06/19 11:44:46 oasisa Exp $ */ /* Summary : Driver Routines for type 2 Shutters for PRR Spectro */ /* Filename : shutter22.c */ /* Author : Dave Wright (dkw) */ /* Project : OASIS Mooring */ /* $Revision: 1.1 $ */ /* Created : 6/25/97 */ /* */ /* MBARI provides this documentation and code "as is", with no warranty, */ /* express or implied, of its quality or consistency. It is provided without*/ /* support and without obligation on the part of the Monterey Bay Aquarium */ /* Research Institute to assist in its use, correction, modification, or */ /* enhancement. This information should not be published or distributed to */ /* third parties without specific written permission from MBARI. */ /* */ /****************************************************************************/ /* Modification History: */ /* 1:06 PM 6/25/97 dkw - created */ /* 11:03 AM 6/26/97 dkw - added direction determination, syntax cleanp */ /* 10:03 AM 6/27/97 dkw - change handling of min/max */ /* 10:56 AM 6/27/97 dkw - modify for re-entrancy, multiple shutters */ /* 1:21 PM 7/1/97 dkw - further clean up of structures */ /* 1:16 PM 7/2/97 dkw - max failure counter */ /* 5:53 PM 7/11/97 dkw - revise structure and sector function */ /* $Log: shut22.c,v $ * Revision 1.1 2001/06/19 11:44:46 11:44:46 oasisa (Oasis users) * Initial revision * * Revision 4.2 98/09/09 10:48:11 10:48:11 bobh (Bob Herlien) * Sept/Oct '98 deployments of M1, Eqpac 1 & 2 * * Revision 4.0 98/03/09 11:44:51 11:44:51 bobh (Bob Herlien) * M3 Deployment of March '98, new Sat-Pac driver * * Revision 3.9 97/10/28 14:00:04 14:00:04 bobh (Bob Herlien) * EqPac Deployment of Nov 1997 * * Revision 3.8 97/09/12 10:51:09 10:51:09 bobh (Bob Herlien) * Redeploy M1 * * Revision 3.7 97/07/23 11:18:32 11:18:32 bobh (Bob Herlien) * July '97 M1 deployment, new shutter code * */ /* */ /****************************************************************************/ /* This module controls a "Shutter", which is a mechanical device designed to cover the optical windows of the Spectroradiometers when not actively sampling. This is to eliminate biofouling which degrades the data obtained by the Spectroradiometers. The shutter contains a DC motor to move the covers, and a potentiometer for determining the position of the covers. The covers are rotated into the desired open or closed position, and the design is such that they can make continuous revolutions in either direction. Drive electronics within the OASIS can consists of an H-Bridge reversible motor drive with overcurrent sensing, and conditioning for the potentiometer that presents position as A/D counts ranging from ~100 to ~800. The motor drive is controlled by two I/O bits known as "control" and "direction". Direction being hi results in increasing A/D counts when in motion, and we refer to this as the "clockwise" direction. Control is a bi-directional bit which when driven hi starts motor motion, and stops it when driven low. When the state of the control bit is read, hi indicates in motion and lo indicates stopped. Once started the motor will continue to run in the direction defined by the direction bit until stopped or an overcurrent event occurs. An overcurrent event is indicative of an obstruction to the mechanism, and the drive electronics will revert to the stopped state automaticly. In an attempt to deal with an obstructed condition, the code that follows implements an algorithm which reverses the direction of rotation when obstructed, taking the "long way around" to the open or closed position. Each invocation of the driver writes a record to the log with the results of the move attempted. In this way we hope to observe the occurance of an obstruction and successful recovery from it in the field. This module assumes the ownership of PIA_A, PORT_C. Sharing of unused bits on this port by other modules has not been implemented. (at some point we should deal with it, but not in this module, dkw.) */ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions */ #include /* OASIS I/O definitions */ #include /* Log record definitions */ #include <80C196.h> /* 80196 Register mapping */ #include /* OASIS Multitasking definitions */ #include /* ARGOS definition */ #include /* shutter definitions */ #ifdef SHUTTER #define NUMBER_OF_SHUTTERS SHUTTER /********************************/ /* External Functions */ /********************************/ Extern Nat16 io_atod( Nat16 channel ); Extern Void drvLog( Driver *dp, Byte *samplep, Int16 len ); Extern volatile Reg Nat16 tick; /* 10 ms ticker */ Extern Void drv_pwron( Driver *dp ); Extern Void drv_pwroff( Driver *dp ); #ifdef ARGOS Extern Void argosShutter( Shutter_data *sdp ); #endif /********************************/ /* External Data */ /********************************/ Extern Reg Byte ioctrl; /* Copy of oasis_ctrl */ Extern Int16 ad_use_cnt; /* Number of people using A/D */ /********************************/ /* Module Local Data */ /********************************/ typedef struct { Nat16 ad_port; Nat16 control_bit; Nat16 dir_bit; } shutter_const ; #if (NUMBER_OF_SHUTTERS == 1) const shutter_const shutter_io[NUMBER_OF_SHUTTERS] = { { SHUTTER0_ANALOG_PORT, 0x01, 0x02 } /* Shutter0: A/D chan, control bitmask, direction bitmask */ }; #else /* For EqPac */ const shutter_const shutter_io[NUMBER_OF_SHUTTERS] = { { SHUTTER0_ANALOG_PORT, 0x01, 0x02 }, /* Shutter0: A/D chan, control bitmask, direction bitmask */ { SHUTTER1_ANALOG_PORT, 0x04, 0x08 } /* Shutter1: A/D chan, control bitmask, direction bitmask */ }; #endif /************************************************************************/ /* Function : initMotor */ /* Purpose : Set up motor drive port */ /* Inputs : Pointer to shutter structure */ /* Outputs : None */ /************************************************************************/ Void initMotor( Shutter_data *sd ) { Byte portbits; portbits = shutter_io[sd->ShutterNumber].control_bit | shutter_io[sd->ShutterNumber].dir_bit; piaa_pdc &= ~portbits; piaa_ddrc |= portbits; } /* take control and direction bits low, set as output. */ /************************************************************************/ /* Function : startMotor */ /* Purpose : Turn on motor drive */ /* Inputs : Pointer to shutter structure */ /* Outputs : None */ /************************************************************************/ Void startMotor( Shutter_data *sd ) { Byte portbits; portbits = shutter_io[sd->ShutterNumber].control_bit; piaa_pdc |= portbits; piaa_ddrc |= portbits; task_delay(2); piaa_ddrc &= ~portbits; } /* take control bit high, set as output, delay for 20MS then set as input */ /************************************************************************/ /* Function : stopMotor */ /* Purpose : Turn off motor drive */ /* Inputs : Pointer to shutter structure */ /* Outputs : None */ /************************************************************************/ Void stopMotor( Shutter_data *sd ) { Byte portbits; portbits = shutter_io[sd->ShutterNumber].control_bit; piaa_pdc &= ~portbits; piaa_ddrc |= portbits; task_delay(15); } /* take control bit low, set as output, delay 150MS to allow coast down */ /************************************************************************/ /* Function : readMotor */ /* Purpose : Return state of motor drive */ /* Inputs : Pointer to shutter structure */ /* Outputs : Boolean, true=running */ /************************************************************************/ MBool readMotor( Shutter_data *sd ) { return(( piaa_pdc & shutter_io[sd->ShutterNumber].control_bit) ? TRUE : FALSE ); } /************************************************************************/ /* Function : setDirMotor */ /* Purpose : Set direction of motor drive */ /* Inputs : Boolean, true=clockwise, pointer to shutter structure */ /* Outputs : None */ /************************************************************************/ Void setDirMotor( MBool clockwise, Shutter_data *sd ) { Byte portbits; portbits = shutter_io[sd->ShutterNumber].dir_bit; if (clockwise) piaa_pdc |= portbits; else piaa_pdc &= ~portbits; } /************************************************************************/ /* Function : readDirMotor */ /* Purpose : Return direction of motor drive */ /* Inputs : None */ /* Outputs : Boolean, true=clockwise */ /************************************************************************/ MBool readDirMotor( Shutter_data *sd ) { return(( piaa_pdc & shutter_io[sd->ShutterNumber].dir_bit) ? CW : CCW ); } /************************************************************************/ /* Function : reverseMotor */ /* Purpose : Reverse direction of motor drive */ /* Inputs : Pointer to shutter structure */ /* Outputs : None */ /************************************************************************/ Void reverseMotor(Shutter_data *sd) { setDirMotor(!readDirMotor(sd),sd); } /************************************************************************/ /* Function : readShutter */ /* Purpose : Return position value */ /* Inputs : Pointer to shutter structure */ /* Outputs : Nat16, shutter position */ /************************************************************************/ Nat16 readShutter(Shutter_data *sd) { return(io_atod(shutter_io[sd->ShutterNumber].ad_port)); } /************************************************************************/ /* Function : sector */ /* Purpose : Determine if we are: Open, Closed, In between. */ /* Inputs : Pointer to shutter structure */ /* Outputs : State value OPEN, CLOSED, INTER */ /************************************************************************/ State sector(Shutter_data *sd) { Nat16 shutterPosition; shutterPosition = readShutter(sd); /* insure A/D read only once */ if((sd->ClosePosition-SHUTTER_CLOSED_SECTOR/2 <= shutterPosition ) && ( shutterPosition <= sd->ClosePosition+SHUTTER_CLOSED_SECTOR/2)) return(CLOSED); if((sd->ClosePosition-SHUTTER_OPEN_SECTOR/2 >= shutterPosition ) || ( shutterPosition >= sd->ClosePosition+SHUTTER_OPEN_SECTOR/2)) return(OPEN); return(INTER); /* must be somewhere else... */ } /************************************************************************/ /* Function : moveShutter dkw */ /* Purpose : Open or shut the shutter */ /* Inputs : Pointer to shutter structure */ /* Outputs : 0 if got there, else error code, TryCount is updated */ /************************************************************************/ Byte moveShutter(Shutter_data *sd) { Nat16 ref_tick; startMotor(sd); ref_tick = tick; --sd->TryCount; while(sector(sd) != (sd->Open ? OPEN : CLOSED)) { if (!readMotor(sd)) /* this handles collisions */ { stopMotor(sd); /* allow coast down */ if ( sd->TryCount <= 0 ) { return(2); /* too many tries error code */ } else { reverseMotor(sd); startMotor(sd); ref_tick = tick; --sd->TryCount; } } if ( (tick - ref_tick) > sd->MaxTicks ) /* taking too long..? */ { stopMotor(sd); return(1); /* timeout error code */ } task_delay(SHUTTER_POLL); /* be a good citizen */ } /* end while */ stopMotor(sd); return(0); /* success */ } /* moveShutter() */ /************************************************************************/ /* Function : RunShutter */ /* Purpose : Operate a shutter */ /* Inputs : Pointer to driver, operation type (open:close) */ /* : PARM0 is shutter number */ /* : PARM1 is closed position calibration */ /* : PARM2 is number of attempts to complete operation */ /* : TIMEOUT is seconds allowed for each attempt */ /* Outputs : Logs results of operation */ /************************************************************************/ Void runShutter(Driver *dp ) { Nat16 ShutterLogData[2]; Shutter_data sd; if( dp->drv_cnt >= MAX_SHUT_FAILURES ) /* drv_cnt used for failure count*/ { dp->drv_flags &= ~DO_SYNC; return; /* just skip it */ } sd.ShutterNumber = dp->drv_parms[PARM0]; sd.Open = dp->drv_usrparm; /* type of operation, */ if ( sd.ShutterNumber >= NUMBER_OF_SHUTTERS ) sd.ShutterNumber = 0; /* on which shutter, */ sd.ClosePosition = dp->drv_parms[PARM1]; /* whose calibration is.. */ sd.TryCount = dp->drv_parms[PARM2]; /* how many attempts allowed */ sd.MaxTicks = TICKS_PER_SECOND * dp->drv_parms[TIMEOUT]; initMotor(&sd); /* set up the I/O port */ ad_use_cnt++; /* Show we're using analog voltage */ ioctrl &= ~ANALOG_DSBL; /* Turn on analog power */ oasis_ctrl = ioctrl; task_delay( TICKS_PER_SECOND/2 ); /* Wait 500 ms for pwr to stabilize */ if(sector(&sd) != (sd.Open ? OPEN : CLOSED)) /* make sure we are not already there */ { drv_pwron(dp); task_delay(10); setDirMotor((readShutter(&sd) < sd.ClosePosition) ? (!sd.Open) : sd.Open, &sd); /* this determines shortest direction to desired condition and presets */ /* the motor control to that direction. clockwise is A/D++ */ if((sd.ErrCode = moveShutter(&sd)) != 0) dp->drv_cnt++; /* do move, accumulate result */ else dp->drv_cnt = 0; #if (NUMBER_OF_SHUTTERS < 2) drv_pwroff(dp); /* we're finished with the motor */ #endif } else { sd.ErrCode = 5; /* redundant operaton code, already there */ } ShutterLogData[0] = readShutter(&sd); /* record where we stopped */ if ( --ad_use_cnt <= 0) /* No longer using analog voltage */ { /* If no one else is, */ ioctrl |= ANALOG_DSBL; /* Turn off analog power */ oasis_ctrl = ioctrl; } dp->drv_flags &= ~DO_SYNC; /* pack shutter status into word as: MS open(bit) number(3bits) error(4bits) count(byte) LS */ sd.TryCount = (0x00FF & (dp->drv_parms[PARM2] - sd.TryCount)); /* TryCount was -- */ ShutterLogData[1] = sd.TryCount; ShutterLogData[1] |= ((sd.ErrCode << 8 ) & 0x0F00); /* pack in error bits, */ ShutterLogData[1] |= ((sd.ShutterNumber << 12) & 0x7000); /* and shutter number */ if (sd.Open) ShutterLogData[1] |= 0x8000; /* set direction bit if appropriate */ drvLog(dp,(Byte *)ShutterLogData,sizeof(ShutterLogData)); /* stash it away... */ #ifdef ARGOS argosShutter( &sd ); /* Tell ARGOS module */ #endif return; /* da da da dat's all folks... */ } /* runShutter() */ #endif @