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

Read rc receiver and control esc


  • Please log in to reply
12 replies to this topic

#1 hampee

hampee

    New Member

  • Members
  • Pip
  • 8 posts

Posted 25 December 2011 - 01:39 PM

I just got my netduino but i need some help to get started. I am somewhat experienced in c# but i dont got a clue on the electronic, so i need some help to get started. My final goal is to make a autonomous boat using gps and a magnometer.But I thought i sould start smaller and just try to make my netduino read a rc reciver and send commands to an esc. I have found some code on this forum but nothing that explains how to wire the reciver and ecs.

#2 gbreder

gbreder

    Advanced Member

  • Members
  • PipPipPip
  • 53 posts
  • LocationGermany

Posted 03 January 2012 - 11:39 AM

Hi hampee,
if you start an autonomous boot a good start would be to control a servo.
You need a class like this:
using System;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;

namespace Netduino.Extender
{
	/// <summary>
	/// private static readonly Servo _Servo = new Servo(Pins.GPIO_PIN_D10);
	/// 
	/// Debug.Print((data2 * 3).ToString());
	/// _Servo.SetPulse(20000, data2 * 3);
	/// </summary>
	public class Servo
	{
		private PWM _Pwm;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="pin">Can be
		/// Pins.GPIO_PIN_D5 or ((Cpu.Pin)0x33),
		/// Pins.GPIO_PIN_D6 or ((Cpu.Pin)0x34),
		/// Pins.GPIO_PIN_D9 or ((Cpu.Pin)0x35),
		/// Pins.GPIO_PIN_D10 or ((Cpu.Pin)0x36).
		/// </param>
		public Servo(Cpu.Pin pin)
		{
			_Pwm = new PWM(pin);
		}

		public void SetDutyCycle(uint onInPercent)
		{
			_Pwm.SetDutyCycle(onInPercent);
		}

		/// <summary>
		/// To set a specific pulse width.
		/// </summary>
		/// <param name="completePeriodInNanoSeconds">For 50Hz servos: 20 ms</param>
		/// <param name="onTimePerPeriodInNanoSeconds">1 ms (left), und 2 ms (right)</param>
		public void SetPulse(uint completePeriodInNanoSeconds, uint onTimePerPeriodInNanoSeconds)
		{
			if (onTimePerPeriodInNanoSeconds > completePeriodInNanoSeconds) throw new InvalidOperationException();

			_Pwm.SetPulse(completePeriodInNanoSeconds, onTimePerPeriodInNanoSeconds);
		}
	}
}
and you can call the contructor like this:
var servo = new Servo(Pins.GPIO_PIN_D5);
or
var servo = new Servo(Pins.GPIO_PIN_D6);
because the Netduino has two pulse width outputs: digital pin 5 and 6.
The servo will be plugged in GND, +5V and digital pin 5 and 6.
Now you can use the SetPulse method to control the angle of the servo. Please read the XML comment of the method. Be aware of the 'ms' in the comment and the 'ns' in the method signature.

To read an RC receiver you have to record all pulses of a digital pin and interpret the length of the current pulse to get the angle. To do this task you have to connect the GND and the signal line to Netduino. The class could start like this
using System;
using Microsoft.SPOT.Hardware;

namespace Netduino.Extender
{
	public sealed class PulseAnalyzer
	{
		private readonly InterruptPort _PulseInputPort;
		
		public PulseAnalyzer(Cpu.Pin dcfSignalPort, Cpu.Pin enableReceptionPort)
		{
			_PulseInputPort = new InterruptPort(dcfSignalPort, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);

			_PulseInputPort.OnInterrupt += DcfInputPortOnInterrupt;
			
		}

		
		private void DcfInputPortOnInterrupt(uint data1, uint data2, DateTime time)
		{
			if (data2 != 0)
			{
				//Signal goes high
				//record the pulse
			}
			else
			{
				//Signal goes low
				//record the pulse
			}
			//analyze pulse with after a complete pulse was received
		}
	}
}

Regards
Guido

#3 hampee

hampee

    New Member

  • Members
  • Pip
  • 8 posts

Posted 03 January 2012 - 01:13 PM

Hi hampee,
if you start an autonomous boot a good start would be to control a servo.
You need a class like this:

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

namespace Netduino.Extender
{
	/// <summary>
	/// private static readonly Servo _Servo = new Servo(Pins.GPIO_PIN_D10);
	/// 
	/// Debug.Print((data2 * 3).ToString());
	/// _Servo.SetPulse(20000, data2 * 3);
	/// </summary>
	public class Servo
	{
		private PWM _Pwm;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="pin">Can be
		/// Pins.GPIO_PIN_D5 or ((Cpu.Pin)0x33),
		/// Pins.GPIO_PIN_D6 or ((Cpu.Pin)0x34),
		/// Pins.GPIO_PIN_D9 or ((Cpu.Pin)0x35),
		/// Pins.GPIO_PIN_D10 or ((Cpu.Pin)0x36).
		/// </param>
		public Servo(Cpu.Pin pin)
		{
			_Pwm = new PWM(pin);
		}

		public void SetDutyCycle(uint onInPercent)
		{
			_Pwm.SetDutyCycle(onInPercent);
		}

		/// <summary>
		/// To set a specific pulse width.
		/// </summary>
		/// <param name="completePeriodInNanoSeconds">For 50Hz servos: 20 ms</param>
		/// <param name="onTimePerPeriodInNanoSeconds">1 ms (left), und 2 ms (right)</param>
		public void SetPulse(uint completePeriodInNanoSeconds, uint onTimePerPeriodInNanoSeconds)
		{
			if (onTimePerPeriodInNanoSeconds > completePeriodInNanoSeconds) throw new InvalidOperationException();

			_Pwm.SetPulse(completePeriodInNanoSeconds, onTimePerPeriodInNanoSeconds);
		}
	}
}


Thanks for your help!

I already got a servo class. But its verry diferent from your code.

     public class Servo
    {
        private PWM pin;

        private uint[] range = new uint[2];

        private const uint maxDegree = 180, minDegree = 0;


        public Servo(Cpu.Pin servoPin)
        {
            pin = new PWM(servoPin);

            pin.SetDutyCycle(0);

            range[0] = 1000;
            range[1] = 2000;
        }

        public void move(double degree)
        {
            if (degree > maxDegree) degree = maxDegree;
            if (degree < minDegree) degree = minDegree;

            pin.SetPulse(20000, (uint)map((long)degree, minDegree, maxDegree, range[0], range[1]));
        }

        public void setRange(uint fullLeft, uint fullRight)
        {
            range[1] = fullLeft;
            range[0] = fullRight;
        }

        private long map(long x, long in_min, long in_max, long out_min, long out_max)
        {
            return (degree - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
        }
    }

I wrote it but it is highly influenced from some code on this forum so i dont take all credit.
unfortunately i havent had a chance to test it yet. But before i do so i thought i sould check with someone more experienced so i dont burn my board.

#4 gbreder

gbreder

    Advanced Member

  • Members
  • PipPipPip
  • 53 posts
  • LocationGermany

Posted 03 January 2012 - 05:48 PM

Hi hampee, nice work. Your Servo class is more sophisticated than mine. Mine has never left the prototyp state. :) If you try to read data from I2C devices to control your boat I suggest you upgrade your Netduino to Firmware 4.2(RC3) or at least 4.1.1 to support the repeated-start bit. Has cost me a few days to realize this :D (and a few more to realize how to upgrade the Netduino) Regards Guido

#5 Chris Seto

Chris Seto

    Advanced Member

  • Members
  • PipPipPip
  • 405 posts

Posted 04 January 2012 - 05:07 AM

I did this with a hobby grade RC car, and I have both a servo lib and ESC lib out here somewhere on the forums. If you do a search for "RWAR", you might be able to find some remains of the project. :)

#6 hampee

hampee

    New Member

  • Members
  • Pip
  • 8 posts

Posted 04 January 2012 - 04:26 PM

I did this with a hobby grade RC car, and I have both a servo lib and ESC lib out here somewhere on the forums. If you do a search for "RWAR", you might be able to find some remains of the project. :)


I found a thread where you had released a great projekt with a ppm decoder class. I have modified it for my projekt and i am just about to test it.
But i would like if someone could confirm i wired right.

Now its wired pin d7 to reciver signal
pin d5 to servo signal
5v and the gnd next to 5v is connected to the reciver
and the +/- from the servo is also connected to reciver.

like this
Posted Image

#7 gbreder

gbreder

    Advanced Member

  • Members
  • PipPipPip
  • 53 posts
  • LocationGermany

Posted 05 January 2012 - 12:00 AM

Hi hampee,
I strongly recommend to wire the +5V directly to a power supply. Maybe you can use a BEC (battery eliminator circuit) from the model.
I've read in another thread (a year ago) that the voltage regulator of the Netduino can not handle the current of the servo if it is blocked or if your program intructs it to go beyound an angle of +/-90 degree. Ground must still be connected to the Netduino and to the other power supply as well.
And I've found a link with specs about current:
How-much-current-can-I-draw-from-Netduino
800mA is the maximum of all loads. If your servo exceed these figures you may be damaging your board.

Regard
Guido

#8 hampee

hampee

    New Member

  • Members
  • Pip
  • 8 posts

Posted 05 January 2012 - 11:33 AM

Hi hampee,
I strongly recommend to wire the +5V directly to a power supply. Maybe you can use a BEC (battery eliminator circuit) from the model.
I've read in another thread (a year ago) that the voltage regulator of the Netduino can not handle the current of the servo if it is blocked or if your program intructs it to go beyound an angle of +/-90 degree. Ground must still be connected to the Netduino and to the other power supply as well.
And I've found a link with specs about current:
How-much-current-can-I-draw-from-Netduino
800mA is the maximum of all loads. If your servo exceed these figures you may be damaging your board.

Regard
Guido


Like this?
Posted Image

I'm sorry if my questions is stupid but i just dont want to start of by damaging my board.

#9 gbreder

gbreder

    Advanced Member

  • Members
  • PipPipPip
  • 53 posts
  • LocationGermany

Posted 05 January 2012 - 11:51 AM

Hi, your drawing looks fine. All devices share a common ground. This should work. :) Guido

#10 hampee

hampee

    New Member

  • Members
  • Pip
  • 8 posts

Posted 01 February 2012 - 12:51 PM

I have done some experimenting but i am not satisfied with they whey i am interacting with my rx reader class.
As for now i have an infinite loop thats constantly is checking the read.
I am trying to make this eventbased so i can have an eventhandler calling a method with the new value if read has been changed but i cant get it to work.
Is it even posible to do it this way?

i have tried doing it like this
        public delegate void readChanged(int read);
        public event readChanged read_changed;

        private InterruptPort pin;

        private long ticks;

        public int min, max;

        public int read
        {
            get
            {
                return read;
            }
            private set
            {
                read = value;
                read_changed(value);
            }
        }

        public rxReader(Cpu.Pin inputPin)
        {
            pin = new InterruptPort(inputPin, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
            pin.OnInterrupt += inputHandle_OnInterrupt;
        }

        void inputHandle_OnInterrupt(uint data1, uint state, DateTime time)
        {
            if (state == 0)
                read = (int)(time.Ticks - ticks) / 10;
            else
                ticks = time.Ticks;
        }


#11 Chris Seto

Chris Seto

    Advanced Member

  • Members
  • PipPipPip
  • 405 posts

Posted 01 February 2012 - 07:08 PM

The Netduino doesn't do a highly accurate job in measuring pulse lengths. There are two options here: First option is to just hook the RX into a pulse counter device. I think some RC shops carry these, especially try DIYdrones. Second option is to write a native driver for the Netduino to read pulse lengths at a native level. This way would require no extra hardware, but will not be quite as easy.

#12 hampee

hampee

    New Member

  • Members
  • Pip
  • 8 posts

Posted 24 February 2012 - 03:58 PM

Can someone send me in the right direction on how to modify the native oninterrupt event so that it also return the puls length

#13 gbreder

gbreder

    Advanced Member

  • Members
  • PipPipPip
  • 53 posts
  • LocationGermany

Posted 27 February 2012 - 10:20 AM

Hi hampee, the event returns a DateTime value each time it is thrown. But as Chris said this is very inaccurate because the resolution is not as high as needed for analyzing normal PWM pulses. Another issue is that some users have experienced out of memory exceptions if the events were thrown with a high frequency. Maybe you should reevaluate your project to see if there is another way to reach your goal. The same has happened to me. My own Home Automation project was redesigned several times and whole PCBs were replaced. A connection via I2C was replaced by a wireless Zigbee connection with ATtiny microcontrollers. I'm happy to share my ideas, but currently it is not clear what your goal is. Regards Guido




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.