Go to Post This isn't an engineering fair and demonstration, it's FRC. Defense is part of the game. You can't expect a good FRC team to just sit there and get clobbered by a full-court shooter; they're going to engineer a solution to the problem. - Kevin Sevcik [more]
Home
Go Back   Chief Delphi > Technical > Programming > Java
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
 
 
Thread Tools Rate Thread Display Modes
Prev Previous Post   Next Post Next
  #6   Spotlight this post!  
Unread 22-02-2011, 15:51
wdell wdell is offline
Registered User
AKA: William Dell
FRC #3999 (Shadetree Mechanics)
Team Role: Mentor
 
Join Date: Jan 2011
Rookie Year: 2010
Location: Killeen, Texas
Posts: 55
wdell has a spectacular aura aboutwdell has a spectacular aura about
Re: Info to Dashboard

Quote:
Originally Posted by Patrickwhite View Post
I've been meaning to write [a class/some classes] that simplif[y/ies] use of the default dashboard, is anyone aware of something similar that already exists? If it does, I'm not going to reinvent the wheel, but it needs better methods than some arbitrarily named methods. The community dashboards are great, but I'd like code that works right out of the box.
Here's what I use to communicate with the driver station and default dashboard:
Code:
package edu.wpi.first.wpilibj.templates;

/**
 * @author   William Dell
 * @author   Team 647
 * @version  v7, January 26, 2011
 * @version  FRC Java version 2011.4
 */
import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.DriverStationLCD;
import edu.wpi.first.wpilibj.Dashboard;
import edu.wpi.first.wpilibj.AnalogModule;
import edu.wpi.first.wpilibj.DigitalModule;
import edu.wpi.first.wpilibj.Solenoid;

/**
 * The routines for dealing with the driver station are ridiculously complicated
 * and cryptic.  Hopefully this class will simplify the process by replacing them
 * with shorter, more obvious methods.
 */
public class DStation implements Runnable {

    // going to treat the LCD as a stack, in reverse here because
    // new lines appear on the bottom and scroll upwards (mostly)
    DriverStationLCD.Line[] lcdLines = {
        DriverStationLCD.Line.kUser6, // bottom line
        DriverStationLCD.Line.kUser5,
        DriverStationLCD.Line.kUser4,
        DriverStationLCD.Line.kUser3,
        DriverStationLCD.Line.kUser2,
        DriverStationLCD.Line.kMain6 // top line
    };
    String[] lcdHistory = new String[6];  // array to scroll lcd display
    String clearLine = "                     "; // 21 spaces to clear a line

    Main robbie;
    // empty constructor
    public DStation(Main mainBot) {
        robbie = mainBot;
    } // end constructor

    /**
     * When run, the class starts a continuous loop to update the dashboard
     * constantly.  This is probably a bad way to do it.
     */
    public void run() {

        // caution, infinite loop, this could be bad....
        while (true) {
            updateDashboard();
        } // end while
        // but it actually works!

    } // end method run()

    /**
     * Messages to the LCD must be 21 characters long or you get artifacts
     * from previous lines.  This should pad the desired message out to 
     * the proper length.
     * 
     * @param msg  the message to be padded out
     * @return  line  the message line padded out to 21 characters
     */
    private String padMsg(String msg) {
        String line = msg;
        if (line.length() < 21) {  // if the message is already 21 or more do nothing
            // otherwise tack on however many spaces we are short
            for (int i = msg.length() + 1; i <= 21; i++) {
                line += " ";
            } // end for
        } // end if
        line = line.substring(0, 21); // make sure we are only 21 long
        return line; // and return the new, padded out line

    } // end method padMsg()

    /**
     * Does just what it says, clears the driver station LCD.
     */
    public void clearLCD() {
        for (int i = 0; i < 6; i++) {
            lcdHistory[i] = clearLine; // clear the lcd "memory"
            // and then use the cleared memory to clear the actual display
            DriverStationLCD.getInstance().println(lcdLines[i], 1, lcdHistory[i]);
        } // end for
        DriverStationLCD.getInstance().updateLCD();  // display the screen

    } // end method clearLCD()

    /**
     * Simplified messages to the LCD, with scrolling; new messages appear at
     * the bottom of the screen and scroll up.
     * 
     * @param msg  the message to be sent to the screen
     */
    public void sendToLCD(String msg) {

        // scroll down the history;  iterate backwards!
        for (int i = 5; i > 0; i--) {
            lcdHistory[i] = clearLine;
            lcdHistory[i] = lcdHistory[i - 1];
        } // end for
        lcdHistory[0] = clearLine; // clear the bottom line of the screen
        lcdHistory[0] = padMsg(msg); // insert new line at the bottom, padded out to 21 chars

        // set up updated screen by rewriting all lines
        for (int i = 0; i < 6; i++) {
            DriverStationLCD.getInstance().println(lcdLines[i], 1, lcdHistory[i]);
        } // end for
        DriverStationLCD.getInstance().updateLCD(); // display the screen

    } // end method sendToLCD()

    /** 
     * This makes it easier to send message to a specific line.  Takes the 
     * desired line number (top to bottom, 1-6) and the message to print as
     * arguments.
     * 
     * @param line  which line of the LCD the message should be displayed on
     * @param msg   the message to be displayed
     */
    public void toLCDLine(int line, String msg) {

        int index = 6 - line; // array is set up bottom to top, this reverses it
        DriverStationLCD.getInstance().println(lcdLines[index], 1, padMsg(msg));
        DriverStationLCD.getInstance().updateLCD(); // keep forgetting this, d'oh!

    } // end method toLCDLine()

    
    /**
     * Taken from DashboardExampleProject.  I'll try to explain how this is 
     * organized.
     * 
     * The LabView dashboard is organized with all the various displays in
     * "clusters".  These clusters are embedded in other clusters, which are
     * embedded in others, and so on.  For example, PWM display 1 is embedded
     * in the cluster for Digital Module 0, which is embedded in Digital
     * Cluster 1, which is in the cluster containing all the digital modules,
     * which is in the cluster containing everything.  Whew.  Basically it's 
     * a tree structure.
     * 
     * To send information to the dashboard, you have to "pack" this tree,
     * filling in all the various clusters with the correct data, and then 
     * send the whole tree at one time to the dashboard.  You create the
     * tree by using the addCluster() method, nesting each lower level of the
     * tree in the higher ones.  When a cluster is loaded you finalize it, 
     * which basically packs up that particular module for shipment to the 
     * dashboard.  After all the clusters are finalized you use the commit()
     * method to send it to the dashboard.
     * 
     * I've extracted the tree structure from the LabView dashboard code to
     * interpret what's below.  I'll try to provide enough comments for you
     * to understand which module is where, and which instrument display it
     * connects to.
     * 
     * To keep the dashboard up to date you have to call this method repeatedly,
     * either in an infinite loop or in teleopContinuous() if you use 
     * IterativeRobot.  I use an infinite loop running in a separate thread.
     */
    void updateDashboard() {
        
        // first, get an instance of the dashboard "packer" file.  This is 
        // essentially a map of how the dashboard has the clusters configured.
        Dashboard lowDashData = DriverStation.getInstance().getDashboardPackerLow();

        // We now recreate the tree using the addCluster method, nesting
        // the individual display panels.
        
        // First, the overall container that holds everything else
        lowDashData.addCluster();  // overall container
        {
            // There are 3 clusters in the next level, the analog modules,
            // the digital modules, and the solenoids.
            
            // Add the cluster containing the analog modules.
            lowDashData.addCluster();
            {
                // The analog module cluster contains two analog modules, one
                // for each of the first two slots on the cRio.
                
                // Add the cluster for Analog Module 0 (Slot One on the cRio)
                lowDashData.addCluster();
                {
                    // Here we just iterate through the analog ports, adding
                    // float values containing the average voltage for the given
                    // port.
                    for (int i = 1; i <= 8; i++) {
                        lowDashData.addFloat((float) AnalogModule.getInstance(1).getAverageVoltage(i));
                    }
                }
                // Finished with Analog Module 0, finalize the cluster
                lowDashData.finalizeCluster(); // finalize analog module 0

                /// Add the cluster for Analog Module 1 (Slot Two on the cRio)
                lowDashData.addCluster();
                {
                    // And again, iterate through the voltages for each port
                    // on the module
                    for (int i = 1; i <= 8; i++) {
                        lowDashData.addFloat((float) AnalogModule.getInstance(2).getAverageVoltage(i));
                    }
                }
                // Finished with Analog Module 1, finalize the cluster.
                lowDashData.finalizeCluster(); // finalize analog module 1
            }
            // Done loading the data for the analog modules, so we finalize
            // the cluster that holds both of them.
            lowDashData.finalizeCluster(); // finalize analog cluster

            // Add the cluster containing the digital sub clusters.
            lowDashData.addCluster();
            {
                // The digital cluster contains two sub clusters, one for
                // slot 4 and one for slot 6 on the cRio.  Each of those
                // clusters contain modules for relays and for the PWM
                // slots.
                
                // Add the cluster for Digital SubCluster 1 (slot 4 on the cRio)
                lowDashData.addCluster();
                {
                    // The digital module itself contains two sub modules.
                    // The numbering system is screwey, but it's taken straight
                    // from the LabView code...
                    
                    // Add the cluster Digital Module 0 in SubCluster 1
                    lowDashData.addCluster();
                    {
                        int module = 4; // this specifies the cRio slot
                        
                        // And the next 4 lines handle relays
                        lowDashData.addByte(DigitalModule.getInstance(module).getRelayForward());
                        lowDashData.addByte(DigitalModule.getInstance(module).getRelayForward());
                        lowDashData.addShort(DigitalModule.getInstance(module).getAllDIO());
                        lowDashData.addShort(DigitalModule.getInstance(module).getDIODirection());

                        // Add the cluster for PWM module 1 - I know for a fact
                        // that these are the 10 PWM connections on the digital
                        // sidecar hooked to the module in cRio Slot 4 :)
                        lowDashData.addCluster();
                        {
                            // Iterate through the PWM values for each port
                            for (int i = 1; i <= 10; i++) {
                                lowDashData.addByte((byte) DigitalModule.getInstance(module).getPWM(i));
                            }
                        }
                        // Finished with PWM Module 1, finalize the cluster.
                        lowDashData.finalizeCluster(); // finalize PWM 1
                    }
                    // And finished with Digital Module 0
                    lowDashData.finalizeCluster(); // finalize digital module 0
                }
                // And with Digital SubCluster 1
                lowDashData.finalizeCluster(); // finalize subcluster 1

                // Add the cluster for Digital SubCluster 2 (slot 6 on the cRio)
                lowDashData.addCluster();
                {
                    // Add the cluster for Digital Module 1 in SubCluster 2
                    lowDashData.addCluster();
                    {
                        int module = 6; // cRio slot 6
                        
                        // And again, load the relay data
                        lowDashData.addByte(DigitalModule.getInstance(module).getRelayForward());
                        lowDashData.addByte(DigitalModule.getInstance(module).getRelayReverse());
                        lowDashData.addShort(DigitalModule.getInstance(module).getAllDIO());
                        lowDashData.addShort(DigitalModule.getInstance(module).getDIODirection());

                        // Add the cluster for PWM Module 2
                        lowDashData.addCluster();
                        {
                            // iterate through all 10 PWM ports
                            for (int i = 1; i <= 10; i++) {
                                lowDashData.addByte((byte) DigitalModule.getInstance(module).getPWM(i));
                            }
                        }
                        // Finished with PWM Module 2, finalize it.
                        lowDashData.finalizeCluster(); // finalize PWM 2
                    }
                    // Finished with Digital Module 2
                    lowDashData.finalizeCluster(); // finalize digital 2
                }
                // And done with Digital SubCluster 2
                lowDashData.finalizeCluster(); // finalize subcluster 2
            }
            // And that completes the entire Digital Cluster
            lowDashData.finalizeCluster(); // finalize digital cluster

            // The solenoids, for some reason, are not in a cluster of their
            // own, but are instead sitting in the overall container.  As such,
            // we don't need to addCluster() for them, we just need to add
            // the data.
            lowDashData.addByte(Solenoid.getAllFromDefaultModule());

            // If you are going to add instruments to the dashboard the
            // easiest place to put them is in the overall cluster, and then 
            // load the values for them here the same way the solenoid was
            // done.  Makes me think the solenoid was an afterthought.
            // Actually I think the whole dashboard was designed haphazardly
            // instead of in a planned manner, which is why this whole structure
            // sucks so bad.

        }
        
        // Once all the inputs are read and loaded, we close the overall container
        lowDashData.finalizeCluster(); // finalize entire tree structure.

        // We are now ready to send our packed up data tree to the dashboard
        // for display.
        lowDashData.commit(); // commit changes to update dashboard

    } // end method updateDashboard()

} // end class DStation
Reply With Quote
 


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 09:35.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi