001 /*----------------------------------------------------------------------------*/ 002 /* Copyright (c) FIRST 2008-2012. All Rights Reserved. */ 003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 004 /* must be accompanied by the FIRST BSD license file in the root directory of */ 005 /* the project. */ 006 /*----------------------------------------------------------------------------*/ 007 008 package edu.wpi.first.wpilibj; 009 010 /** 011 * The MotorSafetyHelper object is constructed for every object that wants to implement the Motor 012 * Safety protocol. The helper object has the code to actually do the timing and call the 013 * motors Stop() method when the timeout expires. The motor object is expected to call the 014 * Feed() method whenever the motors value is updated. 015 * 016 * @author brad 017 */ 018 public class MotorSafetyHelper { 019 020 double m_expiration; 021 boolean m_enabled; 022 double m_stopTime; 023 MotorSafety m_safeObject; 024 MotorSafetyHelper m_nextHelper; 025 static MotorSafetyHelper m_headHelper = null; 026 027 /** 028 * The constructor for a MotorSafetyHelper object. 029 * The helper object is constructed for every object that wants to implement the Motor 030 * Safety protocol. The helper object has the code to actually do the timing and call the 031 * motors Stop() method when the timeout expires. The motor object is expected to call the 032 * Feed() method whenever the motors value is updated. 033 * 034 * @param safeObject a pointer to the motor object implementing MotorSafety. This is used 035 * to call the Stop() method on the motor. 036 */ 037 public MotorSafetyHelper(MotorSafety safeObject) { 038 m_safeObject = safeObject; 039 m_enabled = false; 040 m_expiration = MotorSafety.DEFAULT_SAFETY_EXPIRATION; 041 m_stopTime = Timer.getFPGATimestamp(); 042 m_nextHelper = m_headHelper; 043 m_headHelper = this; 044 } 045 046 /** 047 * Feed the motor safety object. 048 * Resets the timer on this object that is used to do the timeouts. 049 */ 050 public void feed() { 051 m_stopTime = Timer.getFPGATimestamp() + m_expiration; 052 } 053 054 /** 055 * Set the expiration time for the corresponding motor safety object. 056 * @param expirationTime The timeout value in seconds. 057 */ 058 public void setExpiration(double expirationTime) { 059 m_expiration = expirationTime; 060 } 061 062 /** 063 * Retrieve the timeout value for the corresponding motor safety object. 064 * @return the timeout value in seconds. 065 */ 066 public double getExpiration() { 067 return m_expiration; 068 } 069 070 /** 071 * Determine of the motor is still operating or has timed out. 072 * @return a true value if the motor is still operating normally and hasn't timed out. 073 */ 074 public boolean isAlive() { 075 return !m_enabled || m_stopTime > Timer.getFPGATimestamp(); 076 } 077 078 /** 079 * Check if this motor has exceeded its timeout. 080 * This method is called periodically to determine if this motor has exceeded its timeout 081 * value. If it has, the stop method is called, and the motor is shut down until its value is 082 * updated again. 083 */ 084 public void check() { 085 DriverStation ds = DriverStation.getInstance(); 086 if (!m_enabled || ds.isDisabled() || ds.isTest()) 087 return; 088 if (m_stopTime < Timer.getFPGATimestamp()) { 089 System.err.println(m_safeObject.getDescription() + "... Output not updated often enough."); 090 091 m_safeObject.stopMotor(); 092 } 093 } 094 095 /** 096 * Enable/disable motor safety for this device 097 * Turn on and off the motor safety option for this PWM object. 098 * @param enabled True if motor safety is enforced for this object 099 */ 100 public void setSafetyEnabled(boolean enabled) { 101 m_enabled = enabled; 102 } 103 104 /** 105 * Return the state of the motor safety enabled flag 106 * Return if the motor safety is currently enabled for this devicce. 107 * @return True if motor safety is enforced for this device 108 */ 109 public boolean isSafetyEnabled() { 110 return m_enabled; 111 } 112 113 /** 114 * Check the motors to see if any have timed out. 115 * This static method is called periodically to poll all the motors and stop any that have 116 * timed out. 117 */ 118 //TODO: these should be synchronized with the setting methods in case it's called from a different thread 119 public static void checkMotors() { 120 for (MotorSafetyHelper msh = m_headHelper; msh != null; msh = msh.m_nextHelper) { 121 msh.check(); 122 } 123 } 124 }