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.
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:
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.
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
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?
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.
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)?
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.
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;
}
}
}
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!
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
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?
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
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)
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.
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.
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.