Sie sind auf Seite 1von 38

 

Stinger CE Application Development Guide for  

Microsoft Robotics Studio (MSRS) 
 

Author:  Jason Summerour 

November 6, 2007 

 
 

Contents 
Introduction ...................................................................................................................................................................................... 3 
Debugging Environment ................................................................................................................................................................... 4 
Desktop Development Environment ............................................................................................................................................ 4 
Windows CE Development Environment ..................................................................................................................................... 5 
Microsoft Robotics Studio Services ................................................................................................................................................... 6 
Serializer Services Installation ...................................................................................................................................................... 6 
Starting a few Serializer Services ................................................................................................................................................. 8 
Serializer Services Overview ...................................................................................................................................................... 13 
Motor Control Example .............................................................................................................................................................. 15 
Run It! ................................................................................................................................................................................... 22 
Let’s Partner! ......................................................................................................................................................................... 22 
Tick, Tick, Tick… ..................................................................................................................................................................... 23 
Let’s talk about Geometry ..................................................................................................................................................... 26 
Talking to yourself ..................................................................................................................... Error! Bookmark not defined. 
Querying a Line Following Sensor .................................................................................................. Error! Bookmark not defined. 
Organizing a Solution ................................................................................................................................................................. 32 
Solving a Maze ............................................................................................................................... Error! Bookmark not defined. 
Building an MSRS CF Project ........................................................................................................................................................... 33 
COM Port Configuration ................................................................................................................................................................. 34 
Auto Launch MSRS Services ....................................................................................................................................................... 36 
Application Auto Launch ................................................................................................................................................................. 36 
 

 
 

Introduction 
This step‐by‐step guide teaches users how to develop sophisticated Microsoft Robotics Studio (MSRS) applications that leverage 
our Serializer Services and Stinger CE Robotics Kit.  By the end of the guide, you should feel comfortable building new 
applications on top of the Serializer Services and Stinger CE Robotics Kit running under Windows CE 6.0. 

More to come… 

Requirements:  

• Visual Studio 2005 Installed 
• Microsoft Robotics Studio (MSRS) 1.5 framework installed 
• A working knowledge of the MSRS framework (work thru tutorials) 
• Development PC/Laptop 
• Batteries 
• Anything else ?? 

 
 

Debugging Environment 
Debugging applications on the desktop is a great deal easier than debugging applications on an embedded system. Therefore, 
this guide introduces the content by developing applications developed for the desktop under Windows XP.   Once the 
applications have been debugged on the desktop, they will be built for, configured for, and deployed under Windows CE.  This 
logical progression will save the user countless hours of debugging time, and makes the whole development experience a lot of 
fun, which is the point! 

This guide uses two scenarios for developing applications for the Stinger CE. 

• Applications developed and debugged from a development machine under Windows XP. 
• Applications developed on development machine, and deployed/ran under Windows CE 6.0 on the eBox‐2300 

Desktop Development Environment 
To begin with, you will be utilizing the desktop development environment pictured below.  Now would be a good time to hook 
up the hardware as shown in Figure 1.  

 
Figure 1 ‐ Stinger CE Desktop/Debug Environment 

 
 

While the diagram depicts the components in a loose configuration, it’s preferred that your Stinger CE be completely 
assembled.  Thus, all you will have to do is connect the Serializer to your Development Station using an RS‐232 Serial cable.  If 
your development station doesn’t have an RS‐232 port, you can use a USB to RS‐232 adapter cable, or you can purchase a USB 
module from www.roboticsconnection.com and use a USB cable to connect directly to the Serializer. 

    
Figure 2 – USB to RS‐232 Adapter Cable, and USB Module Direct Connection 

Windows CE Development Environment 
Once the applications have been debugged, we will move over to deploying and debugging applications on the eBox‐2300.    

 
Figure 3 ‐ Stinger CE Windows CE Development/Debug Environment 

 
 

Microsoft Robotics Studio Services  
The Serializer Services provide an MSRS service based interface to the RoboticsConnection Serializer WL Robot Controller.  This 
allows customers to easily interface the MSRS framework with a plethora of ready to use robotic components (sensors, motors, 
general purpose I/O, i2c, etc.) that interface with the Serializer.  In this section, we’ll show you how to install and use the 
Serializer Services with our Stinger CE robot, fitted with a basic set of sensors.  Example after example, you will build a working 
application that will allow your robot to follow a line.  Eventually, you will be developing applications of your own. 

This guide will not delve into the fine points of MSRS, and the inner workings.  Rather, it will focus only on getting the Serializer 
Services installed and working, and teach you how to develop orchestration services that leverage those services.  You will have 
to read through the MSRS User Documentation, and work through the Service Tutorials before continuing any further.    That 
way, you will have a better understanding of how MSRS Services work, as well as the terminology used.   The best 
documentation is included in the MSRS 1.5 installation, which includes HTML help files, as well as Service examples.  You can 
download the latest version of MSRS here: 

http://www.microsoft.com/robotics 

Serializer Services Installation 
Let’s start by downloading and installing the Serializer Services for Microsoft Robotics Studio.  At this point, you must have 
MSRS 1.5 Installed on your development machine.  You must also have Visual Studio 2005 installed on your machine (included 
with the eBox‐2300 Jump Start Kit). 

You can download our Serializer Services here: 

http://www.roboticsconnection.com/t‐microsoftroboticsstudio.aspx 

Once you have downloaded the latest Serializer Services zip file, follow these directions for installation: 

1. Open the RoboticsConnection_Services_MSRS_1.5.zip file and extract the contents to the following directory: 
 
  C:\Microsoft Robotics Studio (1.5)\samples\Platforms 
 
2. You should now have the following directories, with appropriate sub‐directories. 
 
  C:\Microsoft Robotics Studio (1.5)\samples\Platforms\RoboticsConnection\SerializerServices 
  C:\Microsoft Robotics Studio (1.5)\samples\Platforms\RoboticsConnection\TraxsterDriveService 
     
3. Open Visual Studio 2005. 
 
4. From the File‐>Open menu, navigate to Microsoft Robotics Studio (1.5)\samples\Platforms\RoboticsConnection 
and double click the RoboticsConnection.sln file to load the Visual Studio solution containing the various projects that 
make up the Serializer Services. 
 
NOTE: For the purpose of this guide, you will not be able to utilize Visual Studio C# Express Edition, since it doesn’t 
support the Compact Framework projects, “cf.SerializerServices”, required for this project. 
 
5. This solution includes the TraxsterDriveService project, but we will not be using that for the purpose of this guide.   
Before we can build the project, we’ll want to disable the TraxsterDriveService from being built.  So, right click on the 
RoboticsConnection solution in the Solution Explorer (top, right), and select Configuration Manager (see Figure 5 & 6 
below).   This will pop up the Configuration Manager dialog.  Uncheck the checkbox in the build column for the 
TraxsterDriveService. 
 

 
 

    
Figure 4 ‐ Opening up the Configuration Manager 

6. Now, build the project.   The SerializerServices project should build first, followed by the cf.SerializerServices 
project.    
 
7. In case you aren’t aware, when you build the Serializer Services, three assemblies are created, and stored under 
 
   C:\Microsoft Robotics Studio (1.5)\bin. 
 
• The main service (or implementation) assembly.  For example, SerializerServices.dll – contains the 
functionality of the service. 
• The proxy assembly.  For example, SerializerServices.proxy.dll – contains the stubs for all the public 
interfaces for the service. 
• The transform assembly.  For example, SerializerServices.transform.dll – contains the code that allows 
types to be converted between the proxy and the service assemblies. 
               
 Three assemblies are also created for the Compact Framework project, and stored under  
 
  C:\Microsoft Robotics Studio (1.5)\bin\CF. 
 
• cf.SerializerServices.dll 
• cf.SerializerServices.proxy.dll 
• cf.SerializerServices.transform.dll 

  To send messages to another service, reference the service's proxy assembly rather than the implementation 
assembly. This is done for a number of reasons: if you are communicating with a service on another node, you may 
not have a copy of the implementation assembly on the local machine; also, by using proxies, the partner service does 
not have any code that executes within the context of your service [Ref: MSRS Service Tutorial #5]. 

8. Copy all of the configuration xml files, which are used to load/save the initial service state, from:  
 
       C:\Microsoft RoboticsStudio(1.5)\samples\Platforms\RoboticsConnection\SerializerServices\Config 
to: 
     C:\Microsoft Robotics Studio (1.5)\bin 
 
When any of the Serializer Services start up, they will look in “C:\Microsoft Robotics Studio (1.5)\bin” for an xml file 
containing their initial state.  If found, the service will populate its initial state with the contents of the xml file.  The 
configuration files have been pre‐populated with a known working state.  If you wish to modify the initial state of any 
of the Serializer Services, modify these files. 
 

 
 

 
9. We will want to modify the state of the SerializerServices.config.xml file to ensure that the COM port is properly 
set for the Serializer Core Service.  Since the Serializer Core Service is a Partner to all of the other Serializer Services, it 
will always get started (if it isn’t already) when any one of the other Serializer Services starts. 
 
 Specifically, change the <ComPort> field to the appropriate COM port that your Serializer is connected to.  You might 
want to use Hyperterm to determine which serial port your local development machine is using to connect to the 
Serializer.  If you’re using a direct serial connection, it will probably be COM1 or COM2, but if you’re using a USB to 
Serial converter, it may be different.   When you determine which port to use, just enter the number of the port, and 
drop the ‘COM’ prefix. 
 
<?xml version="1.0" encoding="utf‐8"?> 
<State xmlns:s="http://www.w3.org/2003/05/soap‐envelope" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" 
xmlns:d="http://schemas.microsoft.com/xw/2004/10/dssp.html" 
xmlns="http://www.roboticsconnection.com/2006/08/Serializer.html"> 
  <TimeStamp>0001‐01‐01T00:00:00</TimeStamp> 
  <ComPort>1</ComPort> 
  <BaudRate>19200</BaudRate> 
  <Version>Not initialized</Version> 
  <Units>English</Units> 
  <IsConnected>false</IsConnected> 
  <InteractiveHistory /> 
</State 
 
10. Make sure you save the SerializerServices.config.xml file. 

Starting a few Serializer Services 
Now that we have successfully built the Serializer services, and put the initial state configuration files in place, let’s start up a 
few services.  For now, we’re just going to start the services on the local development computer.  Later, we will start them up 
under Windows CE on the eBox‐2300. 

Start a new DSS Node via Start‐>All Programs‐>Microsoft Robotics Studio (1.5)‐>Run DssNode.  A command window, as well as 
a web browser should pop up (or another tab should appear within your browser) and you should see the Robotics Studio Web 
Panel as shown below.  Note the URL specified at the top of the browser (http://localhost:50000), which informs us that the 
DSSNode was started up on the local development machine, and it is communicating over port 50000. 

 
 

 
Figure 5 ‐ Robotics Studio Web Panel 

Under System Services in the left hand pane, select ‘Control Panel’.  This will bring up a list of services which are available to use 
on the current DSS Node.  If you scroll down, you’ll see all of the Serializer Services listed.   

Let’s start up a ‘LineSensor Service’ by selecting the ‘Create’ button to the right of the highlighted service (NOTE: The 
highlighted ‘Serializer Core Services’ will automatically get started since it’s a Partner of the LineSensor Service).  Don’t worry 
about specifying a manifest at this point, since the services know which partners to rely on. 

 
 

 
Figure 6 ‐ Robotics Studio Service Control Panel 

Now, select the ‘Service Directory’ web page from the left hand pane.  This will bring up the Service Instance Directory, 
displaying the instances of services currently running.   
 
You should see highlighted ‘/linesensorservice’ and ‘/serializer’ instances listed in the right hand pane.  This means that the 
services were started up properly.   If you do not see these service instances listed, click on the ‘Debug and Trace Messages’ to 
figure out why the services didn’t start. 
 

 
 

 
 
Figure 7 ‐ Service Instance Directory 

Now if you click on the /serializer link, a web page, displaying the current state of the Serializer, will display in the browser.   
 
You might think “Wow!”, the Serializer state has a nice web interface.  This is because the state, which is stored in xml (as you 
saw a few steps ago), has been transformed from xml to html using an XSLT stylesheet (see MSRS Service Tutorial #6).  Had a 
stylesheet not been applied, you would see the state displaying in raw xml (identical to that stored in the configuration files). 
 
You will notice that not only is the state provided, but there are a few controls as well.  The controls allow you to change the 
COM port, as well as type in any Serializer command you wish, and send it directly.  Once you type a command, it is saved in 
History, for you to use again.  This is a very useful debugging facility, so remember that it’s available. 
 
Rather than changing the SerializerServices.config.xml file, we could have waited until now to change the COM port; however, 
it will prove beneficial later when we start developing orchestration services. 
 
The status displayed on the page tells you if the Serializer Core service was able to connect with the Serializer board.  In the 
picture below, it was unable to connect.  Once a connection is made, the status will change to ‘Connected’, and the latest 
version of the Serializer firmware will be displayed. 

 
 

 
 
Figure 8 ‐ Serializer Core Service State 

Now let’s navigate back to the Service Instance Directory page, and click on the /linesensorservice link.   This will bring up a web 
page containing the LineSensor service state, rendered in pretty html, featuring a few user controls. 
 

 
Figure 9 ‐ LineSensor Service State 

 
 

You can set the value of I2CAddress, and UpdateFrequency state members by entering their values in the text boxes, and 
clicking ‘Update’.  These values will be used the next time the Line Sensor is queried. 
 
Once a Serializer Core Service connects to an actual Serializer with a Line Sensor attached, you can move a white/black line in 
front of the sensor, hit ‘Refresh Page’ at the bottom of the browser page, and you will see the circles update to reflect the 
values that the sensor sees.  If the Serializer cannot communicate with the Line Sensor (e.g. incorrect address), then the circles 
will be red, indicating it wasn’t able to query the values. 
 
Before we go and develop an orchestration service to leverage the Serializer Services, let’s talk about how the Serializer 
Services are structured in the next section. 
 

Serializer Services Overview 
While it isn’t necessary for you to fully understand the internal workings of the Serializer Services, it would be good to have a 
basic understanding of how they work.  This will also help you debug problems that arise going forward. 

The Serializer Services were written as a collection of separate services that allow users to pick and choose from the 
functionality supported by the Serializer, À la carte.   

The following services are currently included in the Serializer Services: 

• Serializer Core* (required by all subsequent services) 
• Gpio (General Purpose I/O) 
• Motor (Pwm Motor Control) 
• Pid (Proportional Integral Derivative Motor Control) 
• AirTemp Sensor 
• Cmps03 Sensor 
• Encoder Sensor (Wheel encoders) 
• Gp2d12 Sensor (Infrared Distance Sensor) 
• Gp2d120 Sensor (Infrared Distance Sensor) 
• Line Sensor 
• Maxez1 (Sonar Distance Sensor) 
• SRF08 (Sonar Distance Sensor) 
• Tpa81 (Temperature Sensor) 
• Servo 

The Serializer Core service is the only service which communicates with the Serializer board directly, via a serial port.  All other 
Serializer Services (e.g. PID, Line Sensor, etc.) require the use of the Serializer Core service, as a Partner, to communicate w/ the 
physical Serializer board. 

The Serializer Core service exposes the ‘Execute’ operation, which is called by the other Serializer services (e.g. PID, Line Sensor, 
etc.) to send a command to the Serializer board.  Once the response is received, it is posted back to the original service invoking 
the operation. 

To better understand how this is accomplished study the diagram below, where a Line Sensor service sends a command to the 
Serializer Core Service, which then sends it to the Serializer board.  The Serializer then queries the Line Sensor, and returns its 
current value back.  The Serializer Core service receives the response, and then sends it back to the Line Sensor service, which is 
then stored in its internal state. 

 
 

Line Sensor Service Serializer Core Service


2
Main Port Timer
Handler()
Execute (‘line 80’)
Main Port 3
Execute
Handler
Timer Port 7
1 Sensor State 9 Handle Response (‘00100’) Response
Response() Port

Timeout Status [0,0,1,0,0] 8


(100) COM
Port

6 4
‘00100’ ‘line 80’

Line Sensor
5
I2C Protocol
Serializer

Line  
Figure 10 ‐ A day in the life of a typical MSRS Serializer Message 

1. The LineSensor’s TimerHandler() is invoked over the TimerPort at a specified UpdateFrequency (Timeout interval) 
2. TimerHandler() creates an Execute message, containing the appropriate command (‘line 80’ in this case), and posts 
the message to the Serializer Service. 
3. The SerializerService has ExecuteHandler() wired so that it will handle Execute messages as they come in over the 
main port. 
4. ExecuteHandler() takes the command in the Execute message, in this case it is ‘line 80’, and sends it over the Serial 
Port to the Serializer. 
5. The Serializer receives the ‘line 80’ command, and then queries the actual Line Sensor at I2C address 80 for its current 
status. 
6. The Serializer sends the Line Sensor status back out the Serial port, which is then received by the ExecuteHandler(). 
7. ExecuteHandler() then posts the response string, via a Response message, back to the Line Sensor Service. 
8. HandleResponse() receives the response message and parses the response string to ensure it’s properly formatted. 
9. HandleResponse() saves the status to the service State. 
10. Other services can now query the Line Sensor service to obtain the latest state/status. 

All Serializer services follow a similar sequence of steps, so you should now be able to look at the code understand how each 
service operates internally.  For example, the SRF08 service periodically sends the appropriate command to query an SRF08 
Sonar Sensor connected to the Serializer, at a specified address.   On the other hand, a GPIO service might send a command to 
the Serializer to set and I/O line from 0 to 1, triggered by a message sent from an orchestration service when a user pressed a 
button. 

Now that you have a basic understanding of how the Serializer services interact w/ the Serializer board, let’s start developing an 
MSRS service application. 

 
 

Motor Control Example 
Let’s start by writing a fun application that can make the Stinger drive around, a specified distance, using the PID (Motor 
Control) Service.   The Serializer has built in Velocity and Distance PID algorithms that allow you to easily command a motor and 
encoder combo to maintain the specified velocity as well as travel the specified distance exactly.   The PID Service serves as an 
interface to that functionality. 

Start by creating a new Simple Dss Service project under C:\Microsoft Robotics Studio 
(1.5)\samples\Platforms\RoboticsConnection as shown below.  Let’s call the project ‘StingerCEApp’. 

 
Figure 11 ‐ Creating a new StingerCEApp Dss Service Project 

Now, we need to add in a reference to the Serializer Services.  Right click on ‘References’, then select ‘Add Reference’.  An Add 
Reference Dialog will appear, and you will need to scroll down to the ‘SerializerServices.Y2006.M08.Proxy’ Component Name, 
and select it.  If you do not see the SerializerServices.Y2006.M08.Proxy, then you probably haven’t built the SerializerServices. 

 
Figure 12 ‐ Add Reference 

 
 

 
Figure 13 ‐ Adding SerializerServices.Y2006.M08.Proxy dll 

The SerializerServices.Y2006.M08.Proxy will appear under the list of References as shown. 

 
Figure 14 ‐ SerializerServices.Y2006.M08.Proxy added to References 

Since we’re interested in invoking the public interfaces provided by the SerializerServices, we can just add the 
SerializerServices.Y2006.M08.Proxy assembly. 

Finally, select the SerializerServices.Y2006.M08.Proxy assembly in the Solution Explorer and set the Copy Local and Specific 
Version fields to False under the Properties Window (lower right). 

Before we continue, let’s attempt to build the solution and ensure that everything is wired up properly.  From the Visual Studio 
menu, select ‘Build’‐>’Build Solution’, or simply press ‘F7’.   You should get a successful build, but if not, make sure your 
references are set up correctly. 

 
 

Before we add any code, let’s talk about how this application will work.  The diagram below depicts the basic communication 
path that our StingerCEApp will use to control the motors using the PIDService.   As you can see, there is a Timer set up in 
StingerCEApp, which will periodically send a ‘SetDistancesRequest’ to the PIDService.  The PIDService, in turn, sends an Execute 
message (containing a ‘digo’ command) to the Serializer.  The Serializer then executes the command, sets the motors to the 
desired speed, and measures the encoder ticks to ensure that the robot travels the exact distance specified.   

Please note that the Serializer will immediately return an ‘ACK’ (if all params were correct), and doesn’t wait on the internal PID 
action to finish.  We provided a ‘pids’ command that can be used to query the state of the PID action, to determine when it has 
completed.  It will return 0 if finished, and 1 if it’s busy. 

Notice the call to ‘SetDistancesRequest’.  The ‘Distances’ refers to the ability to set distance and speed for both motors.  There 
are also other PID Service operations which can control the distance to a single motor.  Likewise, there are operations available 
to control the speed of one or both motors, such as ‘SetVelocityRequest’, and ‘SetVelocitiesRequest’, respectively. 

Furthermore, the PIDService provides operations to configure the PID Distance and Velocity parameters.  However, the default 
PID parameters that work with the Stinger CE robot are already stored in the Serializer by default, and the PID Service uses 
these default values.  The PID parameters are listed below in the PID Service state.  While we won’t cover using these 
operations in this guide, sending messages to configure those properties is similar to sending any other message, and you can 
learn about their exact signatures by perusing the PID Service source code included in the Serializer Services solution you 
previously installed. 

Lastly, the PID Service will send a response back to the StingerCEApp, indicating if the call was a success or failure. 

 
Figure 15 ‐ StingerCEApp Motor Control Diagram 

 
 

Now that we have a clear understanding of how the StingerCEApp will operate, we can start coding.  We’ll start by adding a few 
using statements, so that we can use the Serializer Services.  Open StingerCEApp.cs file from the Solution Explorer.  Add the 
following using statements:

 
Figure 16 ‐ Adding the proper namespaces 

Next, let’s create a new file that we’ll use to store only the state definition in.  Right click the StingerCEApp project in the 
Solution Explorer, then select ‘Add’, then ‘New Item’.  In the Add New Item dialog, select ‘C# Class’, then name the new class 
StingerCEAppState.cs.  Click ‘Add’ to complete the process. 

    
Figure 17 ‐ Adding a new StingerCEAppState class 

You should now see the StingerCEAppState.cs file in the Solution Explorer in the right hand pane.  Double click it to open the 
file.   Also, open up StingerCEAppTypes.cs.    

 
Figure 18 ‐ Open up StingerCEAppState.cs and StingerCEAppTypes.cs 

 
 

Now, cut the Contract and StingerCEApp classes (highlighted below in blue) from StingerCEAppTypes.cs, and paste them in 
StingerCEState.cs.  We’re doing this so that these classes will be contained in a separate state file for ease of use. 

 
Figure 19 ‐ Cut the Contract and State from StingerCEAppTypes.cs, and paste into StingerCEAppState.cs 

Also, add the namespace ‘Microsoft.Dss.Core.Attributes’ to the StingerCEAppState.cs file as shown below.  This is needed for 
the [DataContract()] attribute, which specifies that the StingerCEAppState class is XML serializable.  We also renamed the 
Contract Identifier to use ‘www.roboticsconnection.com’ in the url.  Your StingerCEAppState.cs file should now look like the one 
below. 

 
Figure 20 ‐ Adding Microsoft.Dss.Core.Attributes namespace & updating the Contract Identifier 

 
 

From the Solution Explorer pane, open the StingerCEApp.manifest.xml file, and change the value of the <dssp:Contract>  
element to reflect the updated URL set for the Contract Identifier above (http://www.roboticsconnection.com/2007/11/stingerceapp.html) 

 
Figure 21 ‐ StingerCEApp.manifest.xml 

Now, let’s add a few members to the state (in StingerCEAppState.cs), which will be used to keep track of the drive modes.   
First, add an enumeration, called DriveModes, which will consist of ‘Straight’ and ‘TurnRight’.   Then add a DriveMode property, 
which will be used to keep track of which mode this service is currently operating under.  Don’t forget to adorn the enum and 
and DriveMode classes with the proper [DataContract] and [DataMember] attributes, so that they can be properly serialized! 

 
Figure 22 ‐ Adding DriveMode State members 

It is a good time to hit ‘F7’ and build your project to ensure that it still builds okay. 

Since the StingerCEApp will be serving more in an orchestration role, we shouldn’t need to add too many new message 
interfaces for external services.  However, we’ll definitely want to add HttpGet message.  This is because later, we’ll want to 
retrieve the StingerCEApp’s state in a serialized xml format from a browser.   Furthermore, we’ll be able to apply a stylesheet to 
the xmlified state, and render it using HTML. 

 
 

In the file StingerCETypes.cs, let’s add an HTTPGet message to the list of messages supported by the StingerCEApp’s service 
port.   Also, add the namespace ‘Microsoft.Dss.Core.DsspHttp’. 

 
Figure 23 ‐ Adding HttpGet to the list of messages to service 

  A port is a mechanism through which messages are communicated between services.  A PortSet is just a 
collection of ports.  

Now open StingerCEApp.cs, and add in the namespace ‘Microsoft.Dss.Core.DsspHttp’ at the top of the file.  Now, add an 
HttpGet handler in there to handle incoming HttpGet requests as shown. 

 
Figure 24 ‐ Adding an HttpGet message handler 

  This handler sends an HttpResponseType message to the response port of the HttpGet message. The HTTP 
infrastructure within the DSS node will serialize the provided state to XML and set that as the body of response to the 
HTTP request. 

 
 

Run It! 
Now, let’s build the application again, and run it, by pressing ‘F5’.  While it’s running, open up a web browser, and navigate to 
http://localhost:50000/StingerCEApp.   You should see the serialized state represented in the browser. 

 
Figure 25 ‐ Viewing StingerCEApp state in a browser 

Let’s Partner! 
Now we need partner up with the SerializerServices.  This will allow the StingerCEApp to invoke all of the SerializerService’s 
interfaces, and use the underlying Serializer controller. 

Start by adding the following snippet (highlighted in yellow) in the StingerCEAppService class (StingerCEApp.cs) just after the 
_mainPort creation as shown below.  This will create a port that will allow us to invoke the PIDMotor interface.  

 
Figure 26 ‐ Adding a PID service Partner 

  Notice how the port creations are wrapped with a “#region PORT INITIALIZATION” and “#endregion”.  This isn’t 
required, but I suggest you make liberal use of them.  It will allow you to expand and collapse portions of your code 
down using the ‘+’, ‘‐‘ blocks on the left of the Visual Studio code window.   The SerializerServices have regions for 
Enums, State & Internal Objects, Port Initializataion, Constructors, Message Handler Mapping, Message Handlers, 
Internal Message Handlers, Timer Message Handlers, Http Message Handlers, Subscriptions, and Helper Functions. 

 
 

By specifying that the StingerCEApp needs the PID service as a partner, and specifying a CreationPolicy of ‘UseExistingOrCreate’, 
then when the StingerCEApp starts up, the PID Service will be started automatically, if it hasn’t already been started.  So, this is 
a way to programmatically specify your required partners for the StingerCEApp service.   Likewise, all of the various Serializer 
Services (e.g. PID, GP2D120, LineFollowing, etc.) all specify the SerializerCore service as a partner.  So anytime one of the 
Serializer Services are started, the SerializerCore services is also started, again if it hasn’t been already. 

So, now we have a port to send messages to the PID Service.   Before we do so, let’s set up timing loop that will allow us to 
periodically run through a sequence of steps (drive steps) to make the Stinger CE perform some basic driving. 

Tick, Tick, Tick… 
Since we will want to run through a sequence of steps to make the Stinger CE drive around, we’ll need some way to periodically 
run through the list.  We can set up a periodic loop using a TimeoutPort as shown below.   Basically, StartTimer() will be called 
using a delay (in milliseconds).   The Arbiter.Receive() method defines a one‐time receiver that will take the message sent when 
the timer interval specified in the call to TimeoutPort expires and passes it as the parameter to the anonymous delegate 
specified as the third parameter to Arbiter.Receive(), which is TimerHandler(). 

Once the timing delay has been reached, TimerHandler() will be invoked.  We can then perform whatever we like within the 
handler, and before finishing, StartTimer() needs to be called again.    

Note that the TimeoutPort receiver is not persistent, since the first parameter is false. This is because the port created by the 
TimeoutPort() method receives one message after the specified interval (in this case 1000 milliseconds) expires. 

 
Figure 27 ‐ Adding Timer Methods 

Now, we need to invoke StartTimer() to kick off the timing loop.  We can do that in the call to Start(), which was automatically 
added to StingerCEApp.cs when we generated the DSS application. 

 
Figure 28 ‐ Adding StartTimer() within Start() 

 
 

We’re almost ready to test the Timer handler, but first we need to add a bit of configuration entries to the 
StingerCEApp.manifest.xml.  Basically, we want to add an entry that will allow us to specify the configuration file to use to 
configure the SerializerCore Service.  Specifically, we want to be able to configure the Baud Rate and COM Port. 

To do this, add a new namespace (xmlns:StingerCE), and a <ServiceRecordType> entry as shown below.   This basically says, use 
the SerializerServices.Config.xml file, at http://localhost/mountpoint/bin/SerializerServices.Config.xml to configure the state of 
the SerializerCore service.  The http://localhost/mountpoint resolves to C:\Microsoft Robotics Studio (1.5)\.    

Notice that the <dssp:Contract> points to the contract defined in the SerializerTypes.cs file. 

 
Figure 29 ‐ Adding Serializer Configuration to the Manifest 

Now, we should be set to start up the service, and see the tick() message print to the screen every 1000msec.  So, go ahead and 
start up the service.  If you see errors at runtime, you might not have copied the configuration files to C:\Microsoft Robotics 
Studio (1.5)\bin directory as we did earlier in this guide. 

 
Figure 30 ‐ Console output of StingerCEApp service showing TickHandler() working 

 
 

Now let’s go to the browser, and see what services have been started.  Using the url: http://localhost:50000/directory, you will 
see a list of services currently running on the DSS node.   As you can see, the stingerceapp is running, which used the pidservice 
as a partner, so it started up.  The pidservice needed the serializer as a partner, so it was started too.  Note: The Service 
Instance names shown below are specified in the ServicePort definition for the main port within that service.  It’s a string, so 
you can call it whatever you like. 

 
Figure 31 ‐ Service Instances currently running 

Another interesting thing to look at is the /manifestloaderclient.   It’s responsible for loading the manifest specified, and 
resolving the information within it.   Click on /manifestloaderclient, and you will see that it loaded the manifest specified by the 
StingerCEApp properties (Debug tab‐>Start Options), as well as loaded the appropriate SerializerServices.Config.xml, which has 
our COM Port and Baud Rate configurations it in. 

 
Figure 32 ‐ Manifest Loader CLient 

 
 

Let’s talk about Geometry 
So, now that we know our periodic loop works, we can *finally* add a sequence of steps that invoke the PIDService interfaces 
to control the motors. 

It would make sense to create some functions that can be used to make the robot travel for a specified distance, at a specified 
velocity.   Those functions would create the appropriate PID messages, and send them to the PIDService.  You could add a 
function to make the robot travel in a straight line, rotate, arc, etc.  So, let’s create some Helper functions to do just that. 

We’ll need to know some geometrical data about the Stinger, so that we can translate ticks fed back from the encoders, to 
distances traveled by the robot, based on wheel diameters.   The unloaded wheel diameter of the Stinger is 2.26”.  However, 
once weight is applied to the wheels, as in a driving position, the foam wheels compress a little bit, and the Effective Diameter 
is about 0.010” less.  So, let’s plan on the Effective Wheel Diameter being 2.25”.   This would make the Circumference about 
7.068”.  Thus, one wheel revolution means the Stinger travels 7.068”.  The built in quadrature wheel encoders provide 624 
pulses per shaft (or wheel) revolution.   This means you have about 0.011” of linear resolution per tick.  Not too bad! ☺  
Another way to look at it is that you get about 88 ticks/inch. 

Now, if we know the distance we want to travel, we can multiply that by 88 ticks/inch, to arrive at the number of ticks we need 
to provide to the PIDService. 

Encoder Resolution: 624 Ticks/Rev

Wheel Diameter = 2.25" Circumference
(Pi x Diameter)

7.086"

TRACK
8.69“ Rotational Diameter

Rotational Pivot Point

 
Figure 33 ‐ Stinger Wheel Geometry 

Since this is a specific attribute for the Stinger, it doesn’t make sense for the PIDService to have a TicksPerInch property.  
Rather, it belongs in a service specific to the Stinger.  Thus, let’s add a TicksPerInch state property, which we will used in the 
helper functions to calculate the number of ticks required to travel based on given distances. 

We also need to know the track distance between the centers of the Stinger drive wheels.  This will be important when we 
want to calculate how many ticks it will take to rotate X number of degrees.   The Stinger track distance is approximately 8.69 
inches.  The Stinger pivots about an instant center exactly between its two wheels.   That means the rotational diameter is 
8.69”, and a rotational circumference would be 27.29”.   

 
 

Thus, if we want to calculate how many ticks it takes to rotate an X number of degrees, then we can: 

  Ticks  = ((number of desired degrees / 360)  x  27.29) x TicksPerInch      NOTE: (1 <= degrees <= 360) 

For example, let’s say we want to rotate 180 degrees: 

  Ticks = ((180 / 360) x 27.29) x 88 

  Ticks = 1200 

Each wheel would then need to rotate that distance, in opposing directions, to achieve the desired amount of rotation. 

That’s all great, theoretically; however, in the real world, uneven surfaces, varying motor speeds, and friction affect the amount 
of degrees that the Stinger will actually rotate.  So, don’t be surprised if the Stinger overshoots, or undershoots the target 
rotation amount.   The biggest factor that affects the outcome of the calculation is the Rotational Diameter.  So, you can tweak 
that somewhat to get a better result. 

Okay, now it’s time to implement all of this information in our service.  Let’s start by adding a few new State properties based 
on the geometrical data we just calculated, as shown below. We need to add TicksPerInch, WheelTrack, and 
RotationalDiameter.  Notice that the RotationalDiameter is automatically set when the Wheel Track property changes, and that 
you can query its value directly, but not set it.  These state members will come in handy for calculating ticks based of off 
distances in the helper functions. 

 
Figure 34 ‐ Adding Geometrical State Members to StingerCEAppState 

 
 

Now, let’s start adding those helper functions in the StingerCEAppService class.   We need functions to allow use to set single 
and dual PID motor velocities and distances.  Being able to set PID Motor velocities and speeds atomically is important, since 
we’ll want both motors to start simultaneously, hence the need for dual PID motor velocity and distance control.  We’ll also 
want some simple drive functions to allow us to drive in a straight line, and rotate.   The following helper functions achieve 
these requirements. 

 
Figure 35 ‐ DoPidDistance() helper function 

 
Figure 36 ‐DoDualPidDistance() helper function 

 
 

 
Figure 37 ‐ DoPidVelocity() helper function 

 
Figure 38 ‐ DoDualPidVelocity() helper function 

 
Figure 39 ‐ DoStopAll() helper function 

 
 

 
Figure 40 ‐ GoStraight(), RotateRight(), and RotateLeft() helper functions 

Now that we have helper functions available to do the PID messaging for us, let’s add some logic to the TimerHandler() method 
to invoke those functions.  We can also use the DriveMode state member to run through alternating drive sequences to make 
the robot drive in a square.  As you can see below, the logic alternates between driving straight, and turning 90 degrees to the 
right, creating a square driving path. 

 
Figure 41 ‐ Adding logic in TimerHandler() to invoke driving methods 

Now build the application, and resolve any errors that may have been introduced.  For testing, we inserted a Serializer 
Bluetooth module in the Serializer (with an BT Antenna), to have an untethered serial connection to our development machine 
(fitted w/ a Bluetooth radio).  You can choose to purchase a Serializer Bluetooth module for debugging, or you can just use 
some long USB or Serial Cables until we get this application running under CE on the eBox‐2300.   You can also sit your Stinger 
Robot upside down on a box, for testing (which is fine for now). 

 
 

Just for kits, let’s view the StingerCEApp service state again, by navigating to http://localhost:50000/StingerCEApp in a browser.  
You’ll see that you can now view the additional state properties we added. 

 
Figure 42 ‐ Viewing StingerCEApp State 

User Input/Output 
Now that we have had a taste for interfacing one of the Serializer Services, let’s interface another.  Let’s add the ability to 
communicate w/ the Stinger CE robot.  The Stinger CE includes a Push Button I/O (PBIO) board that can be used Input/Output 
to/from the robot.   The PBIO is connected to the Serializer’s I/O header pins.  Thus, we’re going to integrate the GPIO (General 
Purpose I/O) service to allow us to query the state of the Push Buttons on the PBIO board, as well as twiddle the PBIO LEDs, and 
operate the buzzer. 

Additionally, we’re going to want to create a simple state machine, which represents the current Operating State of the service.  
Let’s have three states: Start, Running, and Waiting.  The service will initially enter the Start state.  While briefly here, it will use 
the buzzer to beep once to indicate that the Service has fully started, and that the robot is ready to perform some tasks.  It will 
then automatically enter the Waiting state (never to return to the Start state again).  It will remain in the Waiting state until a 
user presses a button on the PBIO board.  Once this occurs, the StingerCEApp will go into the Running state, and one of the 
PBIO LEDs will be lit. If the user presses the same button again, the Operating mode will return to the Waiting state, and the 
LED will turn off.   

This will give us some useful interaction with the robot, and allow us to debug services going forward. 

 
Figure 43 ‐ StingerCEApp Operating States 

 
 

Now let’s start implementing this state machine.  First, let’s define the operating states within the service.  We’ll do that using 
an Enumeration in the main Service class. 

 
Figure 44 ‐ Operating State Enumeration 

Foo 

Bar 

Bam 

Following a line 
Now that we have had a taste for interfacing one of the Serializer Services, let’s interface another.   This time, we’re going to 
interface the LineSensor service to follow a line through a maze.  We’ll add the logic to follow the line in the StingerCEApp 
service. 

Solving a Maze 
Now that we have had a taste for interfacing one of the Serializer Services, let’s interface another.  However, we’re going to 
create a brand new service yet again.  We’ll develop a stand‐alone service, which can solve a maze.  Why not just build on the 
service we just wrote?  Because a service which can solve a maze could be very useful to others, and it makes sense to 
encapsulate that functionality into a single service, and make reusable. 

We will use the maze solving service…. 

Organizing a Solution 
Before we go off and start creating several projects to perform various tasks, let’s create a common Visual Studio Solution that 
will encompass all projects, and keep them in an organized place.  This will make it easier to refer back to each project as we 
progress through developing more sophisticated services. 

Start up Visual Studio 2005, and go to File‐>New‐>Project.   A New Project dialog box will appear. Under ‘Other Projects’, select 
‘Visual Studio Solutions’, and then highlight ‘Blank Solution’.  Name the Solution ‘Stinger CE’ in the Name field, and then click on 
the ‘Browse’ button, and navigate to: 

C:\Microsoft Robotics Studio (1.5)\samples\Platforms\RoboticsConnection 

To set the Solution location: 

 
 

Finish by clicking the ‘Ok’ button.  A new, empty solution, called StingerCE, will appear. 

Now, we can add the previous LineFollowing project, and other projects as we go along for the various experiments, and have 
them located in one solution. 

Building an MSRS CF Project 
Show how to create a MRS CF project 

 
 

COM Port Configuration 
Before we can develop any applications for Windows CE, we have to ensure that the eBox‐2300s onboard serial port is 
configured properly.   Even though you have created and launched working CE image, you still have to create a Serial 
Connection under CE.   You can do this by following the procedure below: 

1. From the CE 6.0 Desktop, select ‘Settings’, and ‘Network and Dial‐up Connections’ as shown below: 

2. Within the window that pops up, double click on ‘Make New Connection’. 

3. Type in ‘COM1’ to name the port, and select ‘Direct Connection’. 

 
 

4. A Device dialog box will appear.  Within the drop‐down list, select ‘Serial Cable on COM1:’.  Then, click on the 
‘Configure’ button. 

5. The Device Properties dialog box will appear.  Ensure that the Baud Rate, Data Bits, Parity, Stop Bits, and Flow Control 
match those in the image below.  Select ‘OK’, to close the dialog, then click ‘Finish’ on the previous dialog. 

6. Now, we need to ensure that these settings get persisted after a reboot.  To do this, simply select ‘Start’, and then 
‘Suspend’.   The screen will go black.  Now, press a key on the keyboard to bring the Desktop back.  Your serial 
configuration has now been saved, and will persist  a reboot. 

 
 

Auto Launch MSRS Services 
We will show you how to auto launch an MSRS Service. 

Application Auto Launch 
Now that we have a working application, let’s work on getting it automatically launched at boot time.   This actually pretty easy, 
and it can be accomplished in a few steps. 

1. Start by navigating to the SerialCommTest directory under “\Program Files” by right clicking on “My Device” on the 
desktop, and selecting ‘Open’, and then navigate to the directory in Windows Explorer as shown. 

        

2. Right click on the “SerialCommTest.exe” application, and select ‘Copy’ as shown above. 
3. Navigate to the \Windows\Startup folder, and right click the folder to bring up the dialog box as shown below.  Select 
‘Paste Shortcut’ to save the shortcut to this folder. 

4. You should now see the shortcut in the folder, called “Shortcut to SerialCommTest.lnk”.  Right click on the shortcut, 
and select “Properties”. 

 
 

5. The following dialog box will appear.  Click on the ‘Shortcut’ tab.  You should now see the ‘Target’ properties.   Verify 
that it looks correct. 

6. To ensure that this shortcut gets persisted to disk, let’s go to ‘Start’, then, select ‘Suspend’.  Once the screen goes 
black, strike any key on the keyboard to bring the desktop back up. 

 
 

7. The SerialCommTest application is now set up to launch at boot time, so let’s test it.  Turn off the eBox‐2300, and 
then turn it back on.  After the Desktop appears, you should see the SerialCommText application launch after a few 
seconds.  If it does not, then something in the ‘Target’ property link for the Shortcut is probably incorrect (e.g. missing 
or misplaced quotes).  There are a few tricks to launching MSRS services, which we’ll cover in the next chapter. 

Das könnte Ihnen auch gefallen