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.LiveWindowSendable;
012    import edu.wpi.first.wpilibj.parsing.IDevice;
013    import edu.wpi.first.wpilibj.tables.ITable;
014    
015    /**
016     * Compressor object.
017     * The Compressor object is designed to handle the operation of the compressor, pressure sensor and
018     * relay for a FIRST robot pneumatics system. The Compressor object starts a task which runs in the
019     * background and periodically polls the pressure sensor and operates the relay that controls the
020     * compressor.
021     */
022    public class Compressor extends SensorBase implements IDevice, LiveWindowSendable{
023    
024        private DigitalInput m_pressureSwitch;
025        private Relay m_relay;
026        private boolean m_enabled;
027        private Thread m_task;
028        private boolean m_run = true;
029    
030        /**
031         * Internal thread.
032         *
033         * Task which checks the compressor pressure switch and operates the relay as necessary
034         * depending on the pressure.
035         *
036         * Do not call this function directly.
037         */
038        private class CompressorThread extends Thread {
039    
040            Compressor m_compressor;
041    
042            CompressorThread(Compressor comp) {
043                m_compressor = comp;
044            }
045    
046            public void run() {
047                while (m_run) {
048                    if (m_compressor.enabled()) {
049                        m_compressor.setRelayValue(!m_compressor.getPressureSwitchValue() ? Relay.Value.kOn : Relay.Value.kOff);
050                    } else {
051                        m_compressor.setRelayValue(Relay.Value.kOff);
052                    }
053                    try {
054                        Thread.sleep(500);
055                    } catch (InterruptedException e) {
056                    }
057                }
058            }
059        }
060    
061        /**
062         * Initialize the Compressor object.
063         * This method is the common initialization code for all the constructors for the Compressor
064         * object. It takes the relay channel and pressure switch channel and spawns a task that polls the
065         * compressor and sensor.
066         *
067         * You MUST start the compressor by calling the start() method.
068         */
069        private void initCompressor(final int pressureSwitchSlot,
070                final int pressureSwitchChannel,
071                final int compresssorRelaySlot,
072                final int compressorRelayChannel) {
073    
074            m_enabled = false;
075            m_pressureSwitch = new DigitalInput(pressureSwitchSlot, pressureSwitchChannel);
076            m_relay = new Relay(compresssorRelaySlot, compressorRelayChannel, Relay.Direction.kForward);
077    
078            UsageReporting.report(UsageReporting.kResourceType_Compressor, 0);
079    
080            m_task = new CompressorThread(this);
081            m_task.start();
082        }
083    
084        /**
085         * Compressor constructor.
086         * Given a fully specified relay channel and pressure switch channel, initialize the Compressor object.
087         *
088         * You MUST start the compressor by calling the start() method.
089         *
090         * @param pressureSwitchSlot The module that the pressure switch is attached to.
091         * @param pressureSwitchChannel The GPIO channel that the pressure switch is attached to.
092         * @param compresssorRelaySlot The module that the compressor relay is attached to.
093         * @param compressorRelayChannel The relay channel that the compressor relay is attached to.
094         */
095        public Compressor(final int pressureSwitchSlot,
096                final int pressureSwitchChannel,
097                final int compresssorRelaySlot,
098                final int compressorRelayChannel) {
099            initCompressor(pressureSwitchSlot,
100                    pressureSwitchChannel,
101                    compresssorRelaySlot,
102                    compressorRelayChannel);
103        }
104    
105        /**
106         * Compressor constructor.
107         * Given a relay channel and pressure switch channel (both in the default digital module), initialize
108         * the Compressor object.
109         *
110         * You MUST start the compressor by calling the start() method.
111         *
112         * @param pressureSwitchChannel The GPIO channel that the pressure switch is attached to.
113         * @param compressorRelayChannel The relay channel that the compressor relay is attached to.
114         */
115        public Compressor(final int pressureSwitchChannel, final int compressorRelayChannel) {
116            initCompressor(getDefaultDigitalModule(),
117                    pressureSwitchChannel,
118                    getDefaultDigitalModule(),
119                    compressorRelayChannel);
120        }
121    
122        /**
123         * Delete the Compressor object.
124         * Delete the allocated resources for the compressor and kill the compressor task that is polling
125         * the pressure switch.
126         */
127        public void free() {
128            m_run = false;
129            try { m_task.join(); }
130            catch (InterruptedException e) {}
131            m_pressureSwitch.free();
132            m_relay.free();
133            m_pressureSwitch = null;
134            m_relay = null;
135        }
136    
137        /**
138         * Operate the relay for the compressor.
139         * Change the value of the relay output that is connected to the compressor motor.
140         * This is only intended to be called by the internal polling thread.
141         * @param relayValue the value to set the relay to
142         */
143        public void setRelayValue(Relay.Value relayValue) {
144            m_relay.set(relayValue);
145        }
146    
147        /**
148         * Get the pressure switch value.
149         * Read the pressure switch digital input.
150         *
151         * @return The current state of the pressure switch.
152         */
153        public boolean getPressureSwitchValue() {
154            return m_pressureSwitch.get();
155        }
156    
157        /**
158         * Start the compressor.
159         * This method will allow the polling loop to actually operate the compressor. The
160         * is stopped by default and won't operate until starting it.
161         */
162        public void start() {
163            m_enabled = true;
164        }
165    
166        /**
167         * Stop the compressor.
168         * This method will stop the compressor from turning on.
169         */
170        public void stop() {
171            m_enabled = false;
172        }
173    
174        /**
175         * Get the state of the enabled flag.
176         * Return the state of the enabled flag for the compressor and pressure switch
177         * combination.
178         *
179         * @return The state of the compressor thread's enable flag.
180         */
181        public boolean enabled() {
182            return m_enabled;
183        }
184    
185        /*
186         * Live Window code, only does anything if live window is activated.
187         */
188        public String getSmartDashboardType(){
189            return "Compressor";
190        }
191        private ITable m_table;
192        
193        /**
194         * {@inheritDoc}
195         */
196        public void initTable(ITable subtable) {
197            m_table = subtable;
198            updateTable();
199        }
200        
201        /**
202         * {@inheritDoc}
203         */
204        public ITable getTable(){
205            return m_table;
206        }
207        
208        /**
209         * {@inheritDoc}
210         */
211        public void updateTable() {
212            if (m_table != null) {
213                m_table.putBoolean("Enabled", m_enabled);
214                m_table.putBoolean("Pressure Switch", getPressureSwitchValue());
215            }
216        }
217        
218        /**
219         * {@inheritDoc}
220         */
221        public void startLiveWindowMode() {}
222        
223        /**
224         * {@inheritDoc}
225         */
226        public void stopLiveWindowMode() {}
227    }