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 import edu.wpi.first.wpilibj.communication.UsageReporting; 011 import edu.wpi.first.wpilibj.livewindow.LiveWindow; 012 import edu.wpi.first.wpilibj.parsing.IDevice; 013 import edu.wpi.first.wpilibj.tables.ITable; 014 import edu.wpi.first.wpilibj.tables.ITableListener; 015 016 /** 017 * Standard hobby style servo. 018 * 019 * The range parameters default to the appropriate values for the Hitec HS-322HD servo provided 020 * in the FIRST Kit of Parts in 2008. 021 */ 022 public class Servo extends PWM implements IDevice { 023 024 private static final double kMaxServoAngle = 170.0; 025 private static final double kMinServoAngle = 0.0; 026 027 /** 028 * Common initialization code called by all constructors. 029 * 030 * InitServo() assigns defaults for the period multiplier for the servo PWM control signal, as 031 * well as the minimum and maximum PWM values supported by the servo. 032 */ 033 private void initServo() { 034 setBounds(2.27, 0, 0, 0, .743); 035 setPeriodMultiplier(PeriodMultiplier.k4X); 036 037 LiveWindow.addActuator("Servo", getModuleNumber(), getChannel(), this); 038 UsageReporting.report(UsageReporting.kResourceType_Servo, getChannel(), getModuleNumber()-1); 039 } 040 041 /** 042 * Constructor that assumes the default digital module. 043 * 044 * @param channel The PWM channel on the digital module to which the servo is attached. 045 */ 046 public Servo(final int channel) { 047 super(channel); 048 initServo(); 049 } 050 051 /** 052 * Constructor that specifies the digital module. 053 * 054 * @param slot The slot in the chassis that the digital module is plugged into. 055 * @param channel The PWM channel on the digital module to which the servo is attached. 056 */ 057 public Servo(final int slot, final int channel) { 058 super(slot, channel); 059 initServo(); 060 } 061 062 /** 063 * Set the servo position. 064 * 065 * Servo values range from 0.0 to 1.0 corresponding to the range of full left to full right. 066 * 067 * @param value Position from 0.0 to 1.0. 068 */ 069 public void set(double value) { 070 setPosition(value); 071 } 072 073 /** 074 * Get the servo position. 075 * 076 * Servo values range from 0.0 to 1.0 corresponding to the range of full left to full right. 077 * 078 * @return Position from 0.0 to 1.0. 079 */ 080 public double get() { 081 return getPosition(); 082 } 083 084 /** 085 * Set the servo angle. 086 * 087 * Assume that the servo angle is linear with respect to the PWM value (big assumption, need to test). 088 * 089 * Servo angles that are out of the supported range of the servo simply "saturate" in that direction 090 * In other words, if the servo has a range of (X degrees to Y degrees) than angles of less than X 091 * result in an angle of X being set and angles of more than Y degrees result in an angle of Y being set. 092 * 093 * @param degrees The angle in degrees to set the servo. 094 */ 095 public void setAngle(double degrees) { 096 if (degrees < kMinServoAngle) { 097 degrees = kMinServoAngle; 098 } else if (degrees > kMaxServoAngle) { 099 degrees = kMaxServoAngle; 100 } 101 102 setPosition(((degrees - kMinServoAngle)) / getServoAngleRange()); 103 } 104 105 /** 106 * Get the servo angle. 107 * 108 * Assume that the servo angle is linear with respect to the PWM value (big assumption, need to test). 109 * @return The angle in degrees to which the servo is set. 110 */ 111 public double getAngle() { 112 return getPosition() * getServoAngleRange() + kMinServoAngle; 113 } 114 115 private double getServoAngleRange() { 116 return kMaxServoAngle - kMinServoAngle; 117 } 118 119 /* 120 * Live Window code, only does anything if live window is activated. 121 */ 122 public String getSmartDashboardType(){ 123 return "Servo"; 124 } 125 private ITable m_table; 126 private ITableListener m_table_listener; 127 128 /** 129 * {@inheritDoc} 130 */ 131 public void initTable(ITable subtable) { 132 m_table = subtable; 133 updateTable(); 134 } 135 136 /** 137 * {@inheritDoc} 138 */ 139 public void updateTable() { 140 if (m_table != null) { 141 m_table.putNumber("Value", get()); 142 } 143 } 144 145 /** 146 * {@inheritDoc} 147 */ 148 public void startLiveWindowMode() { 149 m_table_listener = new ITableListener() { 150 public void valueChanged(ITable itable, String key, Object value, boolean bln) { 151 set(((Double) value).doubleValue()); 152 } 153 }; 154 m_table.addTableListener("Value", m_table_listener, true); 155 } 156 157 /** 158 * {@inheritDoc} 159 */ 160 public void stopLiveWindowMode() { 161 // TODO: Broken, should only remove the listener from "Value" only. 162 m_table.removeTableListener(m_table_listener); 163 } 164 }