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

Servos on the Netduino Go Shield Base

Servo Netduino Go Shield Base Getting Started with Netduino PWM

  • Please log in to reply
18 replies to this topic

#1 Gutworks

Gutworks

    Advanced Member

  • Members
  • PipPipPip
  • 363 posts
  • LocationOttawa, Ontario

Posted 17 April 2012 - 05:49 PM

I have been trying to convert the code from the book Getting Started with Netduino and the .:oomlout:. Experimenter's Guide for Netduino to drive a servo on the new Shield Base (a slightly modified version of the Expermenter's Guide can also be found in the tutorials section of our Wiki) What I am getting stuck on is the new PWM class v.4.2.0.1 of the 4.2 .NetMf (QEF1). Unlike the PWM class in previous versions, there is no longer a SetPulse() method. Here are the 2 new PWM constructors:

public PWM(Cpu.PWMChannel channel, double frequency_Hz, double dutyCycle, bool invert);public PWM(Cpu.PWMChannel channel, uint period, uint duration, PWM.ScaleFactor scale, bool invert);

What I don't understand is the need for the arguments period and duration in the constructor? Wouldn't you change the Period, or more specifically the Duration members of the class at a later point in order to rotate the servo? Here is my altered version of the code from chapter 7 of Getting Started with Netduino that I'm attempting to use. At the moment it is not working. Any help would be greatly appreciated. Thanks, Steve

 

 

using System;using Microsoft.SPOT;using SecretLabs.NETMF.Hardware.NetduinoGo;using NetduinoGo;using System.Threading;namespace NGo_ShieldBaseServo{    public class Program    {        public static void Main()        {            //Using the Parallax Continuous Rotation Servo            NetduinoGo.ShieldBase shieldBase = new NetduinoGo.ShieldBase(GoSockets.Socket8);            Microsoft.SPOT.Hardware.PWM servo = new Microsoft.SPOT.Hardware.PWM(shieldBase.PWMChannels.PWM_3, 20000, 1500, Microsoft.SPOT.Hardware.PWM.ScaleFactor.Microseconds, false);            uint firstPosition = 1000; //Minimum pulse width of 1ms            uint lastPosition = 2000;  //Maximum pulse width of 2 ms            // move through the full range of positions            for (uint currentPosition = firstPosition;                 currentPosition <= lastPosition;                 currentPosition += 10)            {                // move the servo to the new position.                servo.Duration = currentPosition;                servo.Period = 20000;                servo.Start();                Thread.Sleep(20); //refresh the pulse every 20 milliseconds. This can be servo dependant            }            // return to first position and wait a half second.            servo.Duration = firstPosition;            servo.Period = 20000;            servo.Start();            Thread.Sleep(Timeout.Infinite);        }    }}

Edit: I had forgotten about this post since writing a tutorial on using a Continuous Rotation Servo on the Shield Base. The Shield Base has received several updates, including the PWM. I highly suggest, if you haven't done so already, to flash your Netduino Go and the Shield Base using Chuck's easy to follow guide. Then you can give the Servo tutorial a shot.

 

 


Edited by Gutworks, 30 December 2012 - 10:05 PM.


#2 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 17 April 2012 - 07:36 PM

Hi Gutworks, You are correct that the period and duration should match up to the legacy SetPulse method. Is your sample locking up? Running but not doing anything? Is there a particular line of code we can look at? PWM in NETMF 4.2 does have a few limitations that we didn't have with the old methods--but if you're running into those we might be able to remove those by modifying NETMF's source. Chris

#3 Gutworks

Gutworks

    Advanced Member

  • Members
  • PipPipPip
  • 363 posts
  • LocationOttawa, Ontario

Posted 17 April 2012 - 08:26 PM

Hi Gutworks,

You are correct that the period and duration should match up to the legacy SetPulse method.

Is your sample locking up? Running but not doing anything? Is there a particular line of code we can look at?

PWM in NETMF 4.2 does have a few limitations that we didn't have with the old methods--but if you're running into those we might be able to remove those by modifying NETMF's source.

Chris

Chris,

Thank you for the quick response. My sample is executing but the servo isn't doing anything, less a small movement on reset which I presume is standard when connected directly to the shield base pins in this simple test. In my actual code I have added debug statements and a LED that blinks for each iteration in the for loop.

I also just realized that I misquoted the original source for the code. I have been testing the code from the Experimenters Guide, but I have also been running through the examples from the book Getting Started with Netduino. I will try and edit my previous post to give credit to the proper author, who I think you may know ;)

Chris can you explain why there is a need to define the period and duration when initializing the new PWM class? Isn't the period and duration somewhat redundant if you are going to change duration later in the code?

Thanks,
Steve

#4 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 17 April 2012 - 08:50 PM

Hi Steve,

Chris can you explain why there is a need to define the period and duration when initializing the new PWM class? Isn't the period and duration somewhat redundant if you are going to change duration later in the code?

That is a good question. I think that the idea is that it might be dangerous to let users start a PWM without a known period and duration. I believe that a duration of zero is disallowed (although I'm not sure why) or else it would make sense to start out there.

Perhaps that question creates a good conversation to bring up as a work item on netmf.codeplex.com? It would be great to have a constructor for PWM that simply took a PWM channel. Even better...one that took the Cpu.Pin instead.

Chris

#5 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 17 April 2012 - 08:51 PM

Hi Steve,

Thank you for the quick response. My sample is executing but the servo isn't doing anything, less a small movement on reset which I presume is standard when connected directly to the shield base pins in this simple test. In my actual code I have added debug statements and a LED that blinks for each iteration in the for loop.

Hmm, very interesting! Were you able to use PWM in another way successfully? Also, do you have a logic analyzer that you could use to see what is being output on the PWM pins?

Finally...to double check, which digital pin do you have your servo connected to? And how is it powered (i.e. what does the wiring look like)?

Chris

#6 Gutworks

Gutworks

    Advanced Member

  • Members
  • PipPipPip
  • 363 posts
  • LocationOttawa, Ontario

Posted 17 April 2012 - 09:07 PM

Hi Steve,


Hmm, very interesting! Were you able to use PWM in another way successfully? Also, do you have a logic analyzer that you could use to see what is being output on the PWM pins?

Finally...to double check, which digital pin do you have your servo connected to? And how is it powered (i.e. what does the wiring look like)?

Chris


I have the servo's black pin to ground on the Shield Base, red to 5V on the Shield Base, and the signal line going to digital pin 10. Unfortunately I don't have a logic analyzer - it's on my long wish list.

I also agree with the above statement, however the ability to provide a scale is nice (micro,milli, or nano).

It would be great to have a constructor for PWM that simply took a PWM channel. Even better...one that took the Cpu.Pin instead.


I was able to pulse a piezo using the other PWM constructor. The code I used as a reference can be found on Aaron's NoobShield thread. This is also where I found which digital pin PWM_3 referenced.

Steve

#7 beastyboy

beastyboy

    Advanced Member

  • Members
  • PipPipPip
  • 194 posts
  • LocationNetherlands

Posted 10 June 2012 - 05:39 PM

Hi Steve,

After reading your story I wanted to try and see if I got those servo's working.
With the below code I got the servo turning 180 degrees and back again.

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

namespace Blinky
{
    public class ServoAndPotentioMeterTest
    {
        //Shieldbase
        static NetduinoGo.ShieldBase shieldBase = new NetduinoGo.ShieldBase(GoSockets.Socket4);
        
        // Potmeter
        static NetduinoGo.Potentiometer potMeter = new Potentiometer(GoSockets.Socket8);
        
        // Stop button
        static InterruptPort button = new InterruptPort(Pins.Button, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);

        // Servo 
        static Microsoft.SPOT.Hardware.PWM servo;
        
        // Timer object just to read the Potentiometer value
        static Timer timer;
        
        // Optional timer state        
        static Object tmpTimerState;
        
        // True when Shieldbase button is pressed quitting application
        static bool ButtonExit = false;

        public static void Main()
        {

            servo = new Microsoft.SPOT.Hardware.PWM(shieldBase.PWMChannels.PWM_2, 20000, 1500, Microsoft.SPOT.Hardware.PWM.ScaleFactor.Microseconds, false);

            // Timer and callback init this has nothing todo with the servo initialisation
            TimerCallback tickEventHandler;
            tickEventHandler = new TimerCallback(timer_Tick);
            tmpTimerState = new Object();
            timer = new Timer(tickEventHandler, tmpTimerState, 20, 20);

            // The button callback then is run when we press the button on the shieldbase
            button.OnInterrupt += new NativeEventHandler(button_OnInterrupt);
            
            servo.Start();
            // Endless loop dont use in normal execution this will just use up energy.
            while (true)
            {
                // Check if button is pressed.
                if (ButtonExit == true)
                {
                    timer.Dispose();
                    break;
                }
                Thread.Sleep(100);
            }
            Thread.Sleep(Timeout.Infinite);
        }

        // Call method that is activated on button press on the Shieldbase
        static void button_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            // Makes the loop break;
            ButtonExit = true;
            // Servo stop dont move.
            servo.Stop();
            
        }

        // This callback is run everytime the period that is set in the callback activates.
        // This can be one second or 10 seconds it is not related to the servo pulse!
        private static void timer_Tick(Object state)
        {

            // Read the value from the potmeter;
            float PotValue = potMeter.GetValue();
            // Based on values of the wikipedia most servo's start at 1000 and up 
            // I based this value on the sound the servo makes when it reaches his max degree.
            // Mine stopped hissing at the lowest value of 1020 and maxed out on 4820
            // These values could be different for another servo I used a 180 degree S1903
            // from ACE R/C
            float ptValue = 1020 + (PotValue * 3700);
            servo.Duration = (uint)ptValue;
        }
   }
}
Hope you get it working.
Olaf

Van SchOten Ict Diensten en Services
http://www.voids.nl


#8 Gutworks

Gutworks

    Advanced Member

  • Members
  • PipPipPip
  • 363 posts
  • LocationOttawa, Ontario

Posted 10 June 2012 - 09:22 PM

Olaf, first and foremost, welcome to the forums! It's been great having you drop by the chat room lately, and now here.

Secondly, awesome job with your code sample. It works great on my system and is so far the only PWM example that I do not have to restart my computer to run more than once. However, as discussed in the chat room, there is a bit of a servo glitch at startup, and it takes several seconds before the application starts in the debugger.

I think you hit on some key points in chat:

BeastBoy - If you look thru the debugger you see that the values of the protected members, like Period, are not the same as the public values they are swapped some how. So that is why I think the servos make strange noises when you start the app and the moment these values are swapped the servo sets again. The PWM signal stays on the servo until you set a new value, so the call back is only there so do something with the value and not to set it again.


I think this will be a fantastic example for Chris to test against. Again, thank you repo and keep the examples coming!

Cheers,
Steve

#9 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 10 June 2012 - 09:50 PM

Olaf, thanks for the repro! And welcome to the Netduino community! Chris

#10 beastyboy

beastyboy

    Advanced Member

  • Members
  • PipPipPip
  • 194 posts
  • LocationNetherlands

Posted 10 June 2012 - 11:02 PM

Thanks Steve and Chris for the feedback, I do however want to point out that the problem Steve had with the changed method names should be resolved. So the SetPulse method from the previous framework version should be available in the newer version. And also the constructor should be the same. Why? Well for me as a starter it was frustrating to pickup a netduino sample and see that its methods are not known in the newer version. How on earth could I know? If we don't standardize the API all video's on you tube and HTML pages describing how to do stuff are worthless for the beginner. Porting from one language to another is a big and tedious job but please make it so that beginners just can take a piece of c# code and move it from one netduino to the other. This is not criticism on the people doing this terrific job, but I just want to point out how it reflex on the people are going to use it. I hope you could look into this. Olaf

Van SchOten Ict Diensten en Services
http://www.voids.nl


#11 beastyboy

beastyboy

    Advanced Member

  • Members
  • PipPipPip
  • 194 posts
  • LocationNetherlands

Posted 11 June 2012 - 10:41 AM

Demo servo on Netduino Go and attached shieldbase. Cheers, Olaf

Van SchOten Ict Diensten en Services
http://www.voids.nl


#12 Stefan

Stefan

    Moderator

  • Members
  • PipPipPip
  • 1965 posts
  • LocationBreda, the Netherlands

Posted 11 June 2012 - 11:20 AM

Demo servo on Netduino Go and attached shieldbase.

Awesome! Love how you use the rubber feet sticker on your servo :)

Groeten uit Brabant,
Stefan
"Fact that I'm a moderator doesn't make me an expert in things." Stefan, the eternal newb!
My .NETMF projects: .NETMF Toolbox / Gadgeteer Light / Some PCB designs

#13 Gutworks

Gutworks

    Advanced Member

  • Members
  • PipPipPip
  • 363 posts
  • LocationOttawa, Ontario

Posted 11 June 2012 - 09:15 PM


        private static void timer_Tick(Object state)
        {

            // Read the value from the potmeter;
            float PotValue = potMeter.GetValue();
            // Based on values of the wikipedia most servo's start at 1000 and up 
            // I based this value on the sound the servo makes when it reaches his max degree.
            // Mine stopped hissing at the lowest value of 1020 and maxed out on 4820
            // These values could be different for another servo I used a 180 degree S1903
            // from ACE R/C
            float ptValue = 1020 + (PotValue * 3700);
            Debug.Print("PotValue: " + PotValue);
            Debug.Print("ptValue: " + ptValue);
            servo.Duration = (uint)ptValue;
        }
  


Olaf, I was trying to fine tune the code for my servo by adding a couple Debug.Print statements to the timer_Tick callback method. When I add the statements, as shown above, VS hangs and is seemingly stuck in a deployment state.

I would like to see if you can reproduce the same result. If you can, can you post the results?

Thanks,
Steve

#14 beastyboy

beastyboy

    Advanced Member

  • Members
  • PipPipPip
  • 194 posts
  • LocationNetherlands

Posted 11 June 2012 - 11:33 PM

Steve my project.

servo project

Cheers,
Olaf

Van SchOten Ict Diensten en Services
http://www.voids.nl


#15 Billy Propes

Billy Propes

    Advanced Member

  • Members
  • PipPipPip
  • 33 posts
  • LocationVincent, OH, USA

Posted 12 June 2012 - 06:47 AM

Hey Guys,

I am having a problem with the PWM on the ShieldBase board. I will eventually use it to run a DC motor from an Arduino Motor Driver board.

However, right now, I am just trying to create a simple "Blinky LED" to debug the PWM. I am using PWM channel 5 on the ShieldBase which, based on a list in another post on the forum, is GPIO_PIN11. I have a resistor and LED hooked up between GPIO_PIN11 and GND.


My code is as follows:

Imports Microsoft.SPOT
Imports Microsoft.SPOT.Hardware
Imports SecretLabs.NETMF.Hardware
Imports SecretLabs.NETMF.Hardware.NetduinoGo
Imports NetduinoGo.ShieldBase
Imports Toolbox.NETMF.Hardware

Module Module1
    Sub Main()
        Dim sb As New NetduinoGo.ShieldBase(GoSockets.Socket1)
        'Setup PWM to 1Hz (1 Blink Per Second), 50% Duty Cycle
        Dim PWM_B As New PWM(sb.PWMChannels.PWM_5, CType(1, Double), CType(50, Double), False)
        PWM_B.Start()
        While (True)
        End While
    End Sub
End Module

I know the hardware is setup correctly, because the following code works correctly (which should have the same effect):

Imports Microsoft.SPOT
Imports Microsoft.SPOT.Hardware
Imports SecretLabs.NETMF.Hardware
Imports SecretLabs.NETMF.Hardware.NetduinoGo
Imports NetduinoGo.ShieldBase
Imports Toolbox.NETMF.Hardware

Module Module1
    Sub Main()
        Dim sb As New NetduinoGo.ShieldBase(GoSockets.Socket1)
        Dim PWM_B As New OutputPort(sb.Pins.GPIO_PIN_D11, False)
        While (True)
            PWM_B.Write(True)
            Thread.Sleep(1000)
            PWM_B.Write(False)
            Thread.Sleep(1000)
        End While
    End Sub
End Module


Anybody got any ideas as to why the first version isn't working? Any help would be greatly appreciated!! Thanks

#16 Gutworks

Gutworks

    Advanced Member

  • Members
  • PipPipPip
  • 363 posts
  • LocationOttawa, Ontario

Posted 13 June 2012 - 04:17 AM

Module Module1
    Sub Main()
        Dim sb As New NetduinoGo.ShieldBase(GoSockets.Socket1)
        'Setup PWM to 1Hz (1 Blink Per Second), 50% Duty Cycle
        Dim PWM_B As New PWM(sb.PWMChannels.PWM_5, CType(1, Double), CType(50, Double), False)
        PWM_B.Start()
        While (True)
        End While
    End Sub
End Module

Hi BillyPropes,

Welcome to the Netduino community!

It looks like your values for the Frequency and DutyCycle may be off. The DutyCycle property should be a double value between 0.0 and 1.0. In your case if you want to set the DutyCycle to 50% use the value .5.

As for the Frequency, I must admit I'm a little baffled and can't tell you what the best value should be. I do know that I generally use 100 as a good value with no flicker. In testing your code I found that at 50% DutyCycle I have a range from 16-999 for the Frequency, with 16 giving a noticeable flicker. If someone else can further explain the Frequency property I would be more than pleased.

I hope this helps.

Dim PWM_B As New PWM(sb.PWMChannels.PWM_5, 100, 0.5, False)

Cheers,
Steve

#17 Billy Propes

Billy Propes

    Advanced Member

  • Members
  • PipPipPip
  • 33 posts
  • LocationVincent, OH, USA

Posted 14 June 2012 - 02:58 AM

Thanks Steve, I see what you mean by the duty cycle being off. Thanks for pointing that out. I was using a whole number for 50% and it should have been a decimal (.50). I did change that and it still didn't give me the intended results though. By setting the frequency to 1Hz and the duty cycle to 50%, it should be turning the LED on for .5 seconds and then off for .5 seconds. But, at this frequency, it never even comes on. I would love to be able to hook up an O-Scope to the pin and see what's going on. But, unfortunately, that's not in the budget for this project. It appears there is a bug in either NETMF or the drivers for the PWM on the ShieldBase. At this point, there is no way the PWM on the ShieldBase is usable and I can't really use it to control my motor driver. The Go is a absolutely great concept and I love being able to program the uC in VB and C#. Unfortunately, I may have to take a look at using a different uC for this project until they get the bugs worked out of the PWM and the ShieldBase comes out of beta. Maybe a standard Netduino or a Mini.

#18 Gutworks

Gutworks

    Advanced Member

  • Members
  • PipPipPip
  • 363 posts
  • LocationOttawa, Ontario

Posted 14 June 2012 - 03:12 AM

I see what you mean by the duty cycle being off. Thanks for pointing that out. I was using a whole number for 50% and it should have been a decimal (.50). I did change that and it still didn't give me the intended results though.

Yes, unfortunately the lowest frequency I could go was 16.

It appears there is a bug in either NETMF or the drivers for the PWM on the ShieldBase. At this point, there is no way the PWM on the ShieldBase is usable and I can't really use it to control my motor driver.

I know Chris and his collaborators have been working diligently on a PWM fix. Hopefully we'll soon see the results of their hard work.

The Go is a absolutely great concept and I love being able to program the uC in VB and C#. Unfortunately, I may have to take a look at using a different uC for this project until they get the bugs worked out of the PWM and the ShieldBase comes out of beta. Maybe a standard Netduino or a Mini.

It is too bad, and I too would really like to use the Shield base for some of my PWM projects, however I do have to remind myself that it is still in beta. Generally I use the Netduino Plus and I think you'll be pleased with any of the Netduinos.

Keep everyone posted on your projects. I would love to hear some more details on what you are working on.

Cheers,
Steve

#19 Gutworks

Gutworks

    Advanced Member

  • Members
  • PipPipPip
  • 363 posts
  • LocationOttawa, Ontario

Posted 01 October 2012 - 02:22 AM

I had forgotten about this post since writing a tutorial on using a Continuous Rotation Servo on the Shield Base. The Shield Base has received several updates, including the PWM. I highly suggest, if you haven't done so already, to flash your Netduino Go and the Shield Base using Chuck's easy to follow guide. Then you can give the Servo tutorial a shot.

Continuous Rotation Servo on the Shield Base controlled with Potentiometer Tutorial

Cheers,
Steve





Also tagged with one or more of these keywords: Servo, Netduino Go, Shield Base, Getting Started with Netduino, PWM

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.