Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

My first Robot Project


  • Please log in to reply
4 replies to this topic

#1 Asymptot

Asymptot

    Member

  • Members
  • PipPip
  • 19 posts

Posted 08 April 2011 - 04:40 PM

Hi,

I finally completted my robot project.
It's nothing big. It doesn't know where it is going, but it knows an obstacle when it sees one.

I got those parts :

- 2 motors & wheels
- 1 IR range detector
- 1 DFRobot shield
- 1 disc-shaped Popolu chassi
- 1 stabilizing ball

I wrote a specific reusable class for Motors. It is not perfect, since it assumes I am using a DFRobot shield, and the speed is hardcoded (even though I prepared a variable speed for the future.

Here is the class :

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace Robot_Tests
{
    enum Motors
    {
        M1,
        M2
    }
    
    class MotorShield
    {
        public const Cpu.Pin M1 = Pins.GPIO_PIN_D7;
        public const Cpu.Pin E1 = Pins.GPIO_PIN_D6;
        public const Cpu.Pin M2 = Pins.GPIO_PIN_D4;
        public const Cpu.Pin E2 = Pins.GPIO_PIN_D5;
        
        /// <summary>
        /// Represents the motor's speed
        /// </summary>
        private int _speed;
        /// <summary>
        /// Represents the motor's speed
        /// </summary>
        public int Speed
        {
            get
            {
                return _speed;
            }
            set
            {
                _speed = value;
            }
        }

        /// <summary>
        /// Represents the left Motor
        /// regardless the Pin chosen on the Shield
        /// </summary>
        private Motor _leftMotor = new Motor();

        /// <summary>
        ///Represents the right Motor
        /// regardless the Pin chosen on the Shield
        /// </summary>
        private Motor _rightMotor = new Motor();

        public MotorShield()
        {
            //Sets the motors to a default value
            SetMotors(Motors.M1, Motors.M1);
        }
        /// <summary>
        /// Set which motor is right and which motor is left.
        /// </summary>
        /// <param name="MLeft">Motor used as the left Motor</param>
        /// <param name="MRight">Motor used as the right Motor</param>
        private void SetMotors(Motors MLeft, Motors MRight)
        {
            if (MLeft == MRight || MLeft == Motors.M1)
            {
                //Sets a default case in case same motor is chosen twice
                //Sets the case where M1 is left and M2 is right
                _leftMotor.E = new PWM(E1);
                _leftMotor.M = new OutputPort(M1, true);
                _rightMotor.E = new PWM(E2);
                _rightMotor.M = new OutputPort(M2, true);
            }
            else
            {
                //Sets the remainning case : M1 is right and M2 is left
                _rightMotor.E = new PWM(E1);
                _rightMotor.M = new OutputPort(M1, true);
                _leftMotor.E = new PWM(E2);
                _leftMotor.M = new OutputPort(M2, true);
            }
        }

        

        public void MoveForward()
        {
            _leftMotor.M.Write(true);
            _leftMotor.E.SetDutyCycle(100);

            _rightMotor.M.Write(true);
            _rightMotor.E.SetDutyCycle(100);
        }

        public void MoveBackward()
        {
            _leftMotor.M.Write(false);
            _leftMotor.E.SetDutyCycle(50);

            _rightMotor.M.Write(false);
            _rightMotor.E.SetDutyCycle(50);
        }

        public void TurnLeft()
        {
            _leftMotor.M.Write(false);
            _leftMotor.E.SetDutyCycle(50);

            _rightMotor.M.Write(true);
            _rightMotor.E.SetDutyCycle(50);
        }

        public void TurnRight()
        {
            _leftMotor.M.Write(true);
            _leftMotor.E.SetDutyCycle(50);

            _rightMotor.M.Write(false);
            _rightMotor.E.SetDutyCycle(50);
        }

        public void SetSpeed(uint iSpeed)
        {
            _rightMotor.setSpeed(iSpeed);
            _leftMotor.setSpeed(iSpeed);
        }
    }

    /// <summary>
    /// This class represents a single Motor
    /// This is designed for the classic Netduino and will use the 
    /// Netduino classes and conventions
    /// </summary>
    class Motor
    {
        #region Properties
        /// <summary>
        /// E represtens the PWM pin chosen for this Motor speed control
        /// (Conventionnally represented by the letter "E").
        /// </summary>
        private PWM _E;
        public PWM E
        {
            get
            {
                return _E;
            }
            set
            {
                _E = value;
            }
        }

        /// <summary>
        /// M represents the digital pin chosen for this Motor direction control
        /// (Conventionnally represented by the letter "E").
        /// </summary>
        private OutputPort _M;
        public OutputPort M
        {
            get
            {
                return _M;
            }
            set
            {
                _M = value;
            }
        }

        private int _speed;
        public int Speed
        {
            get
            {
                return _speed;
            }
            set
            {
                _speed = value;
            }
        }

        //private OutputPort SpeedPort = new OutputPort(
        #endregion

        #region Constructors

        public Motor()
        {
        }


        public Motor(PWM pwm, OutputPort OutP)
        {
            E = pwm;
            M = OutP;

        }
        #endregion

        public void setSpeed(uint iSpeed)
        {
            if (iSpeed > 100)
            {
                iSpeed = 100;
            }

            E.SetDutyCycle(iSpeed);
        }
    }
}

I also coded an IR Range detector class, but it's nothing new.

Here is the end result :
http://www.youtube.com/watch?v=ercJ2oK5O1I

That's it.
Now I achieved this simple thing, what is the logical next step? Giving it a sense of direction? Making its current direction better by ensuring both motors really run at the same speed? Any suggestion to make it better?

Thanks,
Asymptot

#2 Dan Morphis

Dan Morphis

    Advanced Member

  • Members
  • PipPipPip
  • 188 posts

Posted 08 April 2011 - 05:20 PM

Great work! I do have a few recommendations though. I don't know if you've seen the new auto-property support thats in C# v3, but it will turn this:

...        
        /// <summary>
        /// Represents the motor's speed
        /// </summary>
        private int _speed;
        /// <summary>
        /// Represents the motor's speed
        /// </summary>
        public int Speed
        {
            get
            {
                return _speed;
            }
            set
            {
                _speed = value;
            }
        }
...

into this:

...        
        /// <summary>
        /// Represents the motor's speed
        /// </summary>
        public int Speed { get; set; }
...

Under the hood the compiler will create the backing field, but the code is now visually smaller. I've done this in a lot of the code I've written and it helps me tremendously by reducing the first glance visual complexity of my code.

#3 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 09 April 2011 - 02:01 AM

AHAAHAHAHAHAH I love that crazy little robot. It's so cute (and hyper!)

#4 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 09 April 2011 - 05:51 AM

Under the hood the compiler will create the backing field, but the code is now visually smaller. I've done this in a lot of the code I've written and it helps me tremendously by reducing the first glance visual complexity of my code.


You might want to look at the code generated as I think the compiler generates fairly long names for the backing variable which bloats the assemblies a little. If space becomes tight then using your own backing variable may give smaller code. See this thread and posting ##2 by CW2

Regards
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#5 Asymptot

Asymptot

    Member

  • Members
  • PipPip
  • 19 posts

Posted 09 April 2011 - 03:13 PM

Thank you for the info. I wasn't familiar with that. Now, I would like to improve the project. I think I will try to make my motor class more generic for a start. Then, I noticed the motors don't run at the same speed, even when set at the same PWM. Is there a way to correct that? I dug a bit and saw devices that counted the number of rotation, but I'm not too familiar with that. Any sugestion as what i could add or change to the project will be welcome.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.