Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   C/C++ (http://www.chiefdelphi.com/forums/forumdisplay.php?f=183)
-   -   Programming ultrasonic rangefinders (http://www.chiefdelphi.com/forums/showthread.php?t=110988)

ekapalka 11-01-2013 11:37

Programming ultrasonic rangefinders
 
Hello CD! I have a pretty good targeting method for launching Frisbees figured out, but there's one thing I need to know wow to do first. How to program ultrasonic rangefinders. Basically, I need to get the range and put it into an equation, either in real time or at the push of a button. How do I get it to return the distance (in inches)? I've looked through CD, and found some examples that are pretty elaborate for doing something similar, but not quite what I was looking for. Is there any easy way to do this? Thanks!

Alan Anderson 11-01-2013 16:16

Re: Programming ultrasonic rangefinders
 
What specific sensor are you planning to use, and what kind of signal does it provide to the control system? Some have an analog voltage which is proportional to the range. Others have a PWM signal that varies depending on the range. Still others are a serial (e.g. SPI or I2C) connection that encodes a number.

Whatever you get, it's almost certainly going to be a simple matter of multiplying the value by an appropriate constant to turn it into a distance in whatever units you want.

ekapalka 12-01-2013 22:13

Re: Programming ultrasonic rangefinders
 
We intend to use one Maxbotix MB1010 LV-MaxSonar-EZ1 (from the kit of parts last year (?)) and one Maxbotix MB1361 XL-MaxSonar-AEL0. They both support 3 sensor outputs: Analog Voltage, Serial, ands Pulse Width. I'll keep researching. If it's as simple as multiplication, I may try to find out how to return metres as well.

DonRotolo 12-01-2013 22:45

Re: Programming ultrasonic rangefinders
 
The Maxbotix sensor analog signal provides 0.01 V per inch. That means that 1.2 V is 120 inches. Just read in the analog voltage and the math is pretty straightforward.

Of course you can use the PWM or digital outputs, but I can't help you there.

ekapalka 13-01-2013 16:40

Re: Programming ultrasonic rangefinders
 
Thank you very much for the information. As it turns out, somebody <.< soldered our rangefinder for pulse width. Nothing I can't fix in a day or two once I acquire a soldering iron. In the meantime, is there an easy way to get input from the pulse width?

Alan Anderson 13-01-2013 20:24

Re: Programming ultrasonic rangefinders
 
Getting input from a PWM signal is one thing that I've never found a good way to handle using the available hardware and software of an FRC robot. You can play around with using a filter circuit to turn the signal into an analog voltage and read it that way, but it would take a lot less time to move the output wire to the voltage pin of the sensor.

ekapalka 13-01-2013 22:26

Re: Programming ultrasonic rangefinders
 
Hypothetically, if we did have the sensor wired properly, is it categorized with the WPI class for rangefinders, or would it just be a digitalinput? I've been looking through the WPI documentation and it says that the Ultrasonic class specifically supports the Devantech SRF04 and Vex ultrasonic sensors. I'm not sure if that means it ONLY supports those two, or if those were just examples.

DjScribbles 14-01-2013 10:26

Re: Programming ultrasonic rangefinders
 
You may find this helpful (be sure to grab from my second posting):
http://www.chiefdelphi.com/forums/sh...d.php?t=103028

I posted this last year, it did work, however I wasn't very happy with the sensor itself since it's very easily confused.

Another good method for determining range is to roughly compute it from a known target (such as the 3pt goal).

ekapalka 14-01-2013 11:36

Re: Programming ultrasonic rangefinders
 
Thanks! How would I call the functions from the main robot cpp file? Is it just
Code:

void GetDistance()
{
AnalogChannel *range;
range = new AnalogChannel(1,1);
float volt;
volt = range->GetVoltage();
float inches;                      //float meters;
inches = volt * 100;              //meters = volt * ???;
return inches;
}

?

Alan Anderson 14-01-2013 11:51

Re: Programming ultrasonic rangefinders
 
Quote:

Originally Posted by ekapalka (Post 1214901)
Thanks! How would I call the functions from the main robot cpp file? Is it just
Code:

//schnip
?

Don't use that code. It's simple, obvious, and wrong. You don't want to keep instantiating a new AnalogChannel every time you need to read the distance.

You can use the fancier .h file from the thread where you got that code, but that might be more than you're ready to handle. Joe ("DjScribbles") is right here and can help you understand how to use it. Or you can define the AnalogChannel object once at the beginning of your program and leave out the pair of lines that create it every time in the code you copied.

ekapalka 14-01-2013 13:55

Re: Programming ultrasonic rangefinders
 
Sorry about that! I knew exactly what you meant, but copied/pasted the pseudo-code from that page assuming that AnalogChannel was the name of the .h file (Having not noticed it at the bottom of the post and not being familiar with the actual AnalogChannel WPI class. Additionally, I'm at school, and the router prohibits me from downloading it for some reason). What I meant was, if I'm using the .h file, how would I make references to it in my own code. Thanks!

DjScribbles 14-01-2013 14:31

Re: Programming ultrasonic rangefinders
 
You would instance it much like you would a jaguar, or any other device.

Code:

#include "AnalogRangeFinder.h"

#define ANALOG_CHANNEL_FOR_SONAR 1

class Robot2012 : public IterativeRobot
{
  AnalogRangeFinder sonar;
  public:
  Robot2012(void):sonar(ANALOG_CHANNEL_FOR_SONAR)
  {
  }

  void AutonomousPeriodic(void)
  {
      float distance = sonar.GetRangeInches();
  }
}

START_ROBOT_CLASS(Robot2012);


mrklempae 15-01-2013 17:53

Re: Programming ultrasonic rangefinders
 
am I the only person who can't seem to get this to work? I'm not completely sure how to do this, but one of the other programmers (better than myself) tried to get it working to no avail...

DjScribbles 16-01-2013 10:50

Re: Programming ultrasonic rangefinders
 
Quote:

Originally Posted by mrklempae (Post 1216005)
am I the only person who can't seem to get this to work? I'm not completely sure how to do this, but one of the other programmers (better than myself) tried to get it working to no avail...

The way the sensor is wired is also important, the code I provided is for operating in analog mode (not PWM mode), and the wiring must account for that.

For debugging the sensor itself you can put a multimeter probe on the analog line and see what value it is sending to the cRio (a voltage level that should change the closer the sensor is to something).

Once you see values on the multimeter that correspond to distance, then you debug code. If you need more help, please post actual details on what you've done and what you see.

ScottW of MaxBo 16-01-2013 15:16

Re: Programming ultrasonic rangefinders
 
Good day! This is Tom Bonar from MaxBotix Inc.

I was looking through the Chief Delphi forum, and I have noticed that you were having difficulty getting the sensor connected to the cRio. You may wish to consider looking at the quick-start guide (http://maxbotix.com/articles/016.htm) that we created last year. This guide has a walk through on connecting MaxSonar sensors to control devices. The fundamentals are the same for all MaxSonar sensors, with the big difference for connection purposes being the scaling factor of the Analog Voltage output. For calculating this output please view our Analog Voltage article (http://maxbotix.com/articles/032.htm). We have examples for all of our sensors, as well as integrating directly with a 10 bit Analog Digital converter.

We have also kept the notes from last year's FIRST competition on our Facebook page (link to the 3 links from first email)

https://www.facebook.com/photo.php?f...type=3&theater
https://www.facebook.com/notes/maxbo...77662868954588
https://www.facebook.com/notes/maxbo...45549128832627

Please let me know if you have any questions by emailing frc@maxbotix.com.

On behalf of MaxBotix Inc., I wish all the teams a successful build season.

Best regards,

Tom Bonar
Technical Support
of MaxBotix Inc.
Phone: (218) 454-0766
Fax: (218) 454-0768
Email: frc@maxbotix.com
Web: www.maxbotix.com
Follow us on Facebook at: http://www.facebook.com/pages/MaxBot...25159384204938

Technical support and sales are subject to
the terms and conditions listed on our
website at http://www.maxbotix.com/ MaxBotix,
MaxSonar,EZ0, EZ1, EZ2, EZ3, EZ4, AE0, AE1,
AE2, AE3, AE4, WR1, WRA1, and WRLA1 are
trademarks of MaxBotix Inc.

mrklempae 16-01-2013 20:11

Re: Programming ultrasonic rangefinders
 
I tried using the code you provided, and it compiled. My next problem is printing the distance to the Driver Station in real time to prove the code and/or our sensor works. We copied and pasted the .cpp ad .h file into the BuiltInDefaultCode, then copied your code into the main .cpp file. We made sure the robot was correctly wired. We tried changing the code a little to get data prited, but couldn't print any data (or at least not the right data).
Code:

#include "AnalogRangeFinder.h"
#include <WPILib.h>
#define ANALOG_CHANNEL_FOR_SONAR 1

class Robot2012 : public IterativeRobot
{
  AnalogRangeFinder sonar;
  public:
  Robot2012(void):sonar(ANALOG_CHANNEL_FOR_SONAR)
  {
  }

  void AutonomousPeriodic(void)
  {
  }
        void OperatorControl(void)
        {
                DriverStationLCD *dsLCD = DriverStationLCD::GetInstance();
                float distance = sonar.GetRangeInches();
                while (IsOperatorControl())
                {
                        dsLCD->PrintfLine(DriverStationLCD::kUser_Line1, "My Value is: %d", distance);
                        dsLCD->UpdateLCD();
                        Wait(0.1);
                }}}
}

START_ROBOT_CLASS(Robot2012);

I'm really sorry about this, but I just threw together the code, untested. I don't currently have access to the code we used. Does anyone know how to do this? We tried different things for two hours or so to no avail. We returned data one time (something like 22354698), which I'm pretty sure is WAY out of the sensors range. P.S, ScottW, THANKS! Once we get this part working, that information will be perfect!

DjScribbles 17-01-2013 10:33

Re: Programming ultrasonic rangefinders
 
In the code you posted here, you only read the distance once, then constantly send it to the driver station, this could cause some odd behavior (assuming the sonar has a bit of turn on transient).

Also, if you are using iterative robot, I would suggest using it's Disabled/Autonomous/Teleop functions, instead of the ones used by simple robot (which may not even work). This code should do what you want to do, and uses IterativeRobot functions:

Code:

#include "WPILib.h"
#include "AnalogRangeFinder.h"


typedef enum
{
    ANALOG_CHANNEL_1_RANGE_FINDER = 1,
    ANALOG_CHANNEL_2_UNUSED,
    ANALOG_CHANNEL_3_UNUSED,
    ANALOG_CHANNEL_4_UNUSED,
    ANALOG_CHANNEL_5_UNUSED,
    ANALOG_CHANNEL_6_UNUSED,
    ANALOG_CHANNEL_7_UNUSED,
    ANALOG_CHANNEL_8_UNUSED,
    ANALOG_CHANNEL_9_UNUSED
} ANALOG_CHANNEL_TYPE;

class Robot2012 : public IterativeRobot
{
    AnalogRangeFinder rangeFinder;

    Timer timeInState;
    Timer timeSinceBoot;

    DriverStation *driverStation;
    DriverStationLCD *driverStationLCD;

    // Local variables to count the number of periodic loops performed
    UINT32 m_autoPeriodicLoops;
    UINT32 m_disabledPeriodicLoops;
    UINT32 m_telePeriodicLoops;

public:

    Robot2012(void):
    rangeFinder(ANALOG_CHANNEL_2_RANGE_FINDER),
    timeInState(),
    timeSinceBoot()
    {
        printf("Robot2012 Constructor Started\n");

        // Acquire the Driver Station object
        driverStation = DriverStation::GetInstance();
        driverStationLCD = DriverStationLCD::GetInstance();

        // Initialize counters to record the number of loops completed in autonomous and teleop modes
        m_autoPeriodicLoops = 0;
        m_disabledPeriodicLoops = 0;
        m_telePeriodicLoops = 0;

        printf("Robot2012 Constructor Completed\n");
    }

    /********************************** Init Routines *************************************/

    void RobotInit(void)
    {
        // Actions which would be performed once (and only once) upon initialization of the
        // robot would be put here.
        timeSinceBoot.Start();
        printf("RobotInit() completed.\n");
    }

    void DisabledInit(void)
    {
        m_autoPeriodicLoops = 0;
        m_telePeriodicLoops = 0;
        m_disabledPeriodicLoops = 0;
        timeInState.Reset();
        timeInState.Start();
    }

    void AutonomousInit(void)
    {
        m_autoPeriodicLoops = 0;
        m_telePeriodicLoops = 0;
        m_disabledPeriodicLoops = 0;
        timeInState.Reset();
        timeInState.Start();
    }

    void TeleopInit(void)
    {
        m_autoPeriodicLoops = 0;
        m_telePeriodicLoops = 0;
        m_disabledPeriodicLoops = 0;
        timeInState.Reset();
        timeInState.Start();
    }

    /********************************** Periodic Routines *************************************/
    //These routines run at a determined rate (several times per second, but not sure how many ms each) as long as periodic and continuous routines don't take longer to execute than expected
    void DisabledPeriodic(void)
    {
        m_disabledPeriodicLoops++;
        driverStationLCD->PrintfLine((DriverStationLCD::Line) 4, "Range to target: %f", rangeFinder.GetRangeInches());
    }

    void AutonomousPeriodic(void)
    {
        m_autoPeriodicLoops++;
        driverStationLCD->PrintfLine((DriverStationLCD::Line) 4, "Range to target: %f", rangeFinder.GetRangeInches());
    }

    void TeleopPeriodic(void)
    {
        // increment the number of teleop periodic loops completed
        m_telePeriodicLoops++;
        driverStationLCD->PrintfLine((DriverStationLCD::Line) 4, "Range to target: %f", rangeFinder.GetRangeInches());
    }

    /********************************** Continuous Routines *************************************/
    //These run more frequently than Periodic loops, and should only contain work that requires frequent execution (and doesn't take long to complete)
    //Uncomment these if needed
//    void DisabledContinuous(void)
//    {
//    }
//
//    void AutonomousContinuous(void)
//    {
//    }
//    void TeleopContinuous(void)
//    {
//    }
};

START_ROBOT_CLASS( Robot2012);


ekapalka 17-01-2013 13:26

Re: Programming ultrasonic rangefinders
 
Is there a benefit to using IterativeRobot instead of SimpleRobot? I'm just wondering. We've been writing all of our simple programs using SimpleRobot to demonstrate the various functions of the robot. Thanks for this, by the way! Our primary problem was a bad PWM cable. We'll be testing to see if we can get the new sensor working today.

BradAMiller 18-01-2013 20:11

Re: Programming ultrasonic rangefinders
 
With the recently posted build of WPILib you should be able to see the AnalogChannel show up on the SmartDashboard in Test mode. From there you'll see the voltages that correspond to distances and it will verify that the sensor is working.

See this page for more information about viewing the Test mode values:

http://wpilib.screenstepslive.com/s/...ode-livewindow

As it shows, you can either explicitly set up the test mode values yourself and get meaningful names for the sensors or you can let WPILib automatically add them. There are examples of each case on that page.

Hope this helps.

Brad

DjScribbles 21-01-2013 10:25

Re: Programming ultrasonic rangefinders
 
Quote:

Originally Posted by ekapalka (Post 1217258)
Is there a benefit to using IterativeRobot instead of SimpleRobot? I'm just wondering. We've been writing all of our simple programs using SimpleRobot to demonstrate the various functions of the robot. Thanks for this, by the way! Our primary problem was a bad PWM cable. We'll be testing to see if we can get the new sensor working today.

IterativeRobot is beneficial because it splits up the periodic and continuous functions for you, provides an init function, and discourages putting blocking while loops in your Autonomous/Teleop handlers.

It makes it easier to add all of your code to the periodic functions, and if you need to add some time sensitive code, it can be added into continuous without restructuring your code.

By removing while loops (or hiding them in the base class), it helps prevent getting stuck in auton mode and never getting to teleop, and in general it encourages writing non-blocking code.


All times are GMT -5. The time now is 14:24.

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