J2i.Net

Nothing at all and Everything in general.

Working Around the Missing Real Time Clock in Windows IoT

I've got a project planned involving Windows IoT for which I need the system to have the correct time. The Raspberry Pi with Windows IoT has no real time clock. It initializes the time over NTP when connected to a network. But when not connected to a network the time will be wrong.   It has no support for a real time clock at this point in time. That's no good. I searched for how people have worked around this. A frequent solution was to add a real time IC and have ones solution communicate directly with the real time chip and ignore the native APIs built around time. I don't like this solution. I'd like to maintain compatibility with other systems and not make something that is dependent on a specific implementation of a clock. I wanted a way to get the Raspberry Pi to initialize from the RTC instead of NTP. 

It took a while to create a solution for this because the APIs needed to manipulate the system time are not available to UWP applications. I managed to create a solution with a power shell script, a program that I made, and a real time clock. The complete solution is available at CodeProject.com. Here is a summary of the solution. The stand alone application I made only does two things. It can read the time from the real time clock chip that I used and print it out as a string. It can also look at the system time and set the time in the real time clock to match. I use the latter of these two capabilities to set the time on the real time clock. When ever the system boots up the first of those capabilities is used to expose the current time in the RTC  to the Power Shell environment. From there I can use the Set-Date command to update the system time. I've saved a Power Shell script to run every time the system turns on to do just this. Now when I turn on my Raspberry Pi off network within a few seconds of turning it on it now has the right time. 😊

ViewModelBase and DelegateCommands in Sample Code

I'm working on some sample code for some upcoming blog post. There are two classes that are used throughout the examples and will probably be used in future samples. I wanted to mention them here for future blog post. This is applicable to both UWP and WPF projects. The first is the base class that I use for all of my ViewModel classes. 

using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Threading;


namespace Common
{
    public class ViewModelBase
    {

        public static System.Threading.SynchronizationContext SyncContext;
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                SendOrPostCallback  a = (o) => { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); };
                if (SyncContext == null)
                    a(null);
                else
                    SyncContext.Send(a, null);
                
            }
        }

        protected void OnPropertyChanged(Expression> expression)
        {
            OnPropertyChanged(((MemberExpression)expression.Body).Member.Name);
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

The field SyncContext is needed for code that runs asynchronously on another thread (for WPF projects this is a Dispatcher instead). If the code attached to PropertyChanged interacts with the UI an exception will occur if this interaction happens on a different thread than the one on which the UI controls were created. When the OnPropertyChanged method is called the SyncContext is used to marshal control back to the UI thread.  One of the OnPropertyChanged methods takes as an argument an expression. I prefer to use this when passing the name of the field being updated to the OnPropertyChange handler because it provides the advantage of compile checking for typos in the name and will be updated if the Rename command is used on a property.  The other frequently used class(es) is the DelegateCommand

using System;
using System.Windows.Input;

namespace Common
{
    public class DelegateCommand : ICommand
    {
        public DelegateCommand(Action execute)
            : this(execute, null)
        {
        }

        public DelegateCommand(Action execute, Func canExecute)
        {
            _execute = execute;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            if (_canExecute != null)
                return _canExecute();

            return true;
        }

        public void Execute(object parameter)
        {
            _execute();
        }

        public void RaiseCanExecuteChanged()
        {
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
        }

        public event EventHandler CanExecuteChanged;

        private Action _execute;
        private Func _canExecute;
    }

    public class DelegateCommand<T> : ICommand
    {
        public DelegateCommand(Action<T> execute)
            : this(execute, null)
        {
        }

        public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)
        {
            _execute = execute;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            if (_canExecute != null)
            {

                return _canExecute((T)parameter);
            }

            return true;
        }

        public void Execute(object parameter)
        {
            _execute((T)parameter);
        }

        public void RaiseCanExecuteChanged()
        {
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
        }

        public event EventHandler CanExecuteChanged;

        private Action<T> _execute;
        private Func<T, bool> _canExecute;
    }
}

The DelegateCommand class is used to make commands that can be bound to a button. This allows us to use DataBinding to associate code with a button through data binding. 

First Look at the Microsoft HoloLens

I've had a chance to have some quality time with the Microsoft HoloLens thanks to the Emerging Experiences team. It's an interesting device. Despite the name it doesn't have anything to do with holography. Rather the name seems to be inspired by a metaphor for the experience of using it. Having gotten a chance to do some development I've started writing about my experiences. I wrote in expanded form a blog post published on the Emerging Experiences blog about the history of stereoscopic devices.  I've also wrote about the making of a very simple game-like experience in an article posted on CodeProject.com. More articles are to follow. 

Fallout 4 Pipboy Traffic Logging in C#

Download Code (2.88 mb)

Bethseda Games released Fallout 4 with an accessory application known as Pip-boy. Within the game the main character wears a computing device on the wrist that gives information relevant to what's going on. Current location, objectives, inventory, status, and other information is available through this device. The Pip-boy application communicates with the game to show the same information on one's mobile device. Being able to have this information accessible while playing the game can be a lot more convenient than the alternative; pausing the game to view the same information. 

If you look around on the Internet you can find a couple of sites that talk about the protocol that the game uses to communicate with the application. It appears that creating one's own client for the game isn't difficult. I've got some other ideas on accessory applications that can be made. Rather than test the application against a live network stream initially I wanted to grab the traffic from the Pip-boy application and save it to a file (this makes debugging much easier).  So I made a quick console application that does just this.  I came across information on the communication between the Pip-boy and the game console in a blog entry by Kyle Kelley named "Fallout 4 Service Discovery and Relay"I'd encourage you to go read the entry to see how he figured this out. 

To summarize what's going on there is communication occurring over two channels. For discovery the game console is listening for UDP broadcast messages on port 28000. A client wishing to discover the game console only need broadcast a message with a small JSON payload to get a response back from the machine that host the game. A relay application will both need to request the address of the real game console and also be prepared to respond to the same type of broadcast request so that a real Pip-boy client can discover it. The relay application also needs to make sure it's not discovering itself. If the relay application starts listening for broadcast before making it's own to find the real game machine then it will receive a copy of it's own request. This can be easily remedied by having the relay application not respond to any discovery requests until after it has already found the game machine. While I tested this and found it to work another potential solution is to include additional information in the JSON message that can be used to recognize request that originated on the relay server. The code for making the relay discoverable to the Pip-boy follows.

 

//prepare to respond to incoming discovery requests
UdpClient discoveryListener = new UdpClient(PIP_AUTODISCOVER);
discoveryListener.EnableBroadcast = true;
discoveryListener.BeginReceive(DiscoverRequestReceived, discoveryListener);

When a Pip-boy client broadcast it's request the DiscoverRequestReceived method runs.

const int PIP_AUTODISCOVER = 28000;

static void DiscoverRequestReceived(IAsyncResult result)
{
    //this request is from a remote client. Send back an acknowledgement
    UdpClient discoveryListener = (UdpClient)result.AsyncState;
    IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);

    //If the request came from the machine on which this program is hosted it could
    //be from this very same program! This could result in the program connecting
    //with itself if we don't have a strategy for handling it. For my strategy I will
    //just add something extra to the JSON data that this program can recognize. If
    //you'd like to use a different strategy uncomment the following code if you need
    //to recognize that the request came from the same machine. 
    bool requestFromHostMaching = false;
    var hostEntry = Dns.GetHostByName(Dns.GetHostName());
    var matchingAddress = hostEntry.AddressList.Where((x) => x.Equals(ep.Address)).FirstOrDefault();
    if (matchingAddress != null)
        requestFromHostMaching = true;

    //Parse the response and make sure it appears to be valid
    byte[] data = discoveryListener.EndReceive(result, ref ep);
    string dataString = Encoding.UTF8.GetString(data);
    DiscoverRequest response = (DiscoverRequest)JsonConvert.DeserializeObject(dataString, typeof(DiscoverRequest));
    //If the response is invalid do nothing further. 
    //if the request came from this program ignore it
    if ((response == null) || (response.IsPassthrough))
    {

        discoveryListener.BeginReceive(DiscoverRequestReceived, discoveryListener);
        return;
    }

    Console.Out.WriteLineAsync(String.Format("Request payload: {0}", dataString));

    //Note, the Passthrough member is not part of the request that comes from 
    //the game console. I've added it so that I can recognize requests from my
    //own machine. 
    byte[] responseBytes = StringToBytes(JsonConvert.SerializeObject(new DiscoveryResponse{ IsBusy = isBusy, MachineType = "PC", IsPassthrough = true }));
    discoveryListener.Send(responseBytes, responseBytes.Length, ep);
    Console.Out.WriteLine("[{0}]Discover request received from {1}", DateTime.Now, ep.Address);

    //Listen for next request
    discoveryListener.BeginReceive(DiscoverRequestReceived, discoveryListener);
}

public class DiscoverRequest
{
    public DiscoverRequest()
    {
        IsPassthrough = false;
    }
    public string cmd { get; set; }
    public bool IsPassthrough { get; set; }
}
public class DiscoveryResponse
{
    public DiscoveryResponse()
    {
        IsPassthrough = false;
    }
    public bool IsBusy { get; set; }
    public string MachineType { get; set; }
    public bool IsPassthrough { get; set; }

}

Now that the Pip-boy can discover the relay we still need for the relay to discover the real game console.

//discover the real service
UdpClient client = new UdpClient();
var discoverMessage = JsonConvert.SerializeObject(new DiscoverRequest { cmd = "autodiscover", IsPassthrough = true });

byte[] sendbuf = Encoding.ASCII.GetBytes(discoverMessage);
byte[] recvBuffer = new byte[128];
IPEndPoint ep = new IPEndPoint(IPAddress.Broadcast, PIP_AUTODISCOVER);

client.Send(sendbuf, sendbuf.Length, ep);
recvBuffer = client.Receive(ref ep);
var response = Encoding.ASCII.GetString(recvBuffer);
var responseMessage = JsonConvert.DeserializeObject(response);
Console.WriteLine(response);
Console.Out.WriteLine("[{0}] Game instance found at {1}", DateTime.Now, ep.Address);

With discovery handled all that's left is to ferry the bytes back and forth between the Pip-boy and the game console; a copy of the bytes from the game console will also be written to a file. All the data that we care about will be communicated with TCP/IP. The .Net library allows us to interact with a TCP client as a stream; many of the same methods that one might use for interacting with a file stream can be applied here. The transfer of the bytes is simple. Read some number of bytes from a source. Write those same bytes to a destination and if desired write another copy of those bytes to a file stream.

async static void TransferData(TcpClient sourceClient, TcpClient destinationClient,  Stream saveStream = null)
{
    if (isClosing)
        return;
    try
    {
        var sourceStream = sourceClient.GetStream();
        var destinationStream = destinationClient.GetStream();
        if (sourceStream.CanRead && destinationStream.CanWrite)
        {
            byte[] readBuffer = new byte[1024];
            int bytesRead = await sourceStream.ReadAsync(readBuffer, 0, readBuffer.Length);
            if (bytesRead > 0)
            {
                await destinationStream.WriteAsync(readBuffer, 0, bytesRead);
                if (saveStream != null)
                {
                    await saveStream.WriteAsync(readBuffer, 0, bytesRead);
                    await saveStream.FlushAsync();
                }
            }
            TransferData(sourceClient, destinationClient, saveStream);

        }
    }
    catch (IOException)
    {
        Console.Out.WriteLine("Closing Session");
        isClosing = true;
        sourceClient.Close();
        destinationClient.Close();
    }
}

In the last line of this method it appears to call itself. Whether or not this is recursion I'll leave open to argument. This call will never result in stack space being exhausted. With TransferData being marked as asynchronous a call to this method doesn't result in a call that takes execution a level deeper into the stack. Instead it schedules the execution of this method in the thread pool. The optional last parameter to this method is a stream to which a copy of the data is to be saved. For my purposes I only wanted to save data that was coming from the game console. I provide a file stream for one call to the TransferData method and not another.

TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Any, PIP_CLIENT));
listener.Start();
while (true)
{
    TcpClient remoteClient = listener.AcceptTcpClient();
    isBusy = true;
    ep.Port = PIP_CLIENT;
    TcpClient pipClient = new TcpClient(ep.Address.ToString(), PIP_CLIENT);
    
    FileStream gameMessageCaptureStream = new FileStream("capture.data", FileMode.Create);
    TransferData(pipClient, remoteClient,  gameMessageCaptureStream);
    TransferData(remoteClient, pipClient);

    Console.Out.WriteLine("[{0}] Connection accepted from {1}", DateTime.Now, remoteClient.Client.RemoteEndPoint);

    while (!isClosing)
        Thread.Sleep(100);
    isBusy = true;
    gameMessageCaptureStream.Close();

    Thread.Sleep(50);
    isClosing = false;

}

That's all the code that I used. Now that I've got a saved data stream I've managed to successfully parse all the data that the Pip-boy sends back and forth. I'm still working on understanding it right now.  Once I understand it I hope to make a client in C# for other purposes. 

 

 

Tizen based Speedometer

Just before heading off to the Samsung Developer's conference I had a chance to implement a Tizen based speedometer for the Gear. The Galaxy Gear and Galaxy Gear 2 don't have hardware for determining the user's location or speed. To make a usable application a second executable was needed that would run on the user's phone to use it's location hardware and send the information back to the watch over Bluetooth. The full details of how I did this have been documented and posted on CodeProject.com. You can find the details here

While at the conference I managed to snag a Galaxy Gear S (or three) and decided to modify the application to run as a standalong application on the Gear S. While I was successful at doing this, my general advice is against doing so unless no other method is necessary. There are two reasons I say this. The first is that the Gear S would not generate location/speed updates at a frequency that I considered acceptable (they could be as close together as 2 seconds but seemed to typically be around 10 seconds apart). The phone's location hardware seemed to generate updates about once per second. The second reason I advise against this is to give priority on protecting the watches's battery over the phone's. Given a full charge and light use the phone can last several days on it's battery (and much longer on conservative use). The watch does not have the potential of being able to last nearly as long as the phone. Nevertheless there are still occasions where using the phone's hardware may be desirable; such as when the phone is left behind or location services are disabled and not available on the phone. 

The Tizen Wearable SDK allows the development on Tizen based applications using HTML, JavaScript, and CSS. There are some Tizen specific classes available in JavaScript for accessing hardware specific features (ex: power management), but most of the rest of what is available is based on web standards. A user's speed and location can be acquired using the W3C Geolocation API Specification. There also exists a library called the Tizen Advanced UI (TAU) framework that's useful for constructing UI components and interactions. 

Constructing the UI

The UI is built in HTML. Most of the elements that make up the UI will make sense if you are experienced at editing HTML. There are a few points that have meaning specific to the TAU framework. Throughout the UI some of the CSS classes are associated with TAU behaviours. These include

 

  • ui-page - the contents of this element for a virtual page. Only one virtual page is visible at a time even though there may be several virtual pages in the same HTML file.
  • ui-page-active - marks the virtual page that is currently displayed
  • ui-header - An element with this style will appear at the top of the display
  • ui-footer - an element with this style will appear at the bottom of the page
There are other UI styles that come with the TAU framework (look in tau.js in the source code). The classes ui-page and ui-page-active are most relevant to navigation within the application. Navigation occurs by changing which element has the ui-page-active class. Only one virtual page will have this class set at any given time. The TAU framework will also take care of manipulation of these classes. Navigation can be implemented through what appears to be regular anchor tags. The href attribute for the anchor is set to the ID of the virtual page to which we want to navigate with a # before the name.  The entirity of the contents for the <body> element of the file that forms this application is below (I've omitted the header which contains the CSS and JS files that get included into the interface). 

 

 

 <div class="ui-page ui-page-active" id="main">
 	<div class="ui-header" data-position="fixed">
 		<h2 class="ui-title">Speedometer</h2>
 	</div>	 	 	
 	<div class="content" style='margin:auto;text-align:center;vertical-align:center;height:200px'>
	  	<div style='margin:auto;'  style="height:80%;">
	  		<div  id="speedText">...</div>
	  		<div  id="speedUnitText" ></div>
	  		<div id="statusText"></div>
	  	</div>  
 	</div>
 	<div class="ui-footer appBar">
 		<a href="#settings" data-transition="slideup">
 			<img id="startTracking" src="images/dark/gear.png" class="appBarItem"  />	 			
 		</a>	 		
 	</div>
 </div>	 
 
<div id="settings" class="ui-page">
 	<div class="ui-header" data-position="fixed">
 		<h2 class="ui-title">Settings</h2>
 	</div>
 	<div class="content">
 		<ul class="ui-listview" id="unitsList">	 			
 		</ul>
 		<input type="checkbox" id="keepScreenOn" name="keepScreenOn" />
 		<label style="font-size:1.25em" for="keepScreenOn" onclick="setPowerPolicy()">Keep Screen On</label> 
 	</div>	 	
 </div>

For this application there are only two virtual pages. One is the screen that displays speed. The other is the settings screen. 

Acquiring Speed

Speed information is inexorably linked to location information. To get a user's speed we must request their location. Depending on the resolution of the location information speed information may or may no be available within it (you may receive a location without speed, but never a speed without location). To request location information the geolocation object within the navigator object is used. This method can be used in many other browsers, though if geolocation information is not supported on the browser this object will return null. The object has several methods that can be used to retrieve location information. The one we want to use is called watchLocation. It will begin the cycle of retrieving several location updates until the geolocation object is asked to stop watching. The watchLocation method takes as it's arguments a reference to the method that we want to use to receive location information, a reference to the method that should be called when an error occurs, and optionally an additional parameter that may contain additional information on timeouts or the maximum age of location information. 

function startWatch() {
	if(locationWatchId === null) {
		console.log('starting location watch');
		locationWatchId  = navigator.geolocation.watchPosition(locationUpdate, locationUpdateError, {maximumAge:250})
		console.log('watch id:' + locationWatchId);
	}
}

function locationUpdate( position ) {
	console.log('position update:' + position.toString() + ':' + (new Date()));
	lastPosition = position;
	var currentSpeed = lastPosition.coords.speed;
	hasLocation = true; 
	$('#speedText').html(formatSpeed(currentSpeed));
	$('#speedUnitText').html(currentUnit.label);
	$('#speedText').css('color', '#fff');
}

When I receive the location information I'm using jQuery to display the updated information on the screen. Speed information is received in meters per second. The formatSpeed method is a method that I've made to convert the speed to either miles per hour or kilometers per hour.

Keeping the Screen On

The default power settings on the Galaxy Gear S keep it fairly prompt about turning the screen off. For the speedometer application one might want to keep the screen on. I've included a checkbox in the settings screen that allows the screen to be kept turned on. One of the tizen specific calls is the ability to control the power state of the device. When the checkbox is set I request that the minimum power state of the device to be set to SCREEN_NORMAL. This is sufficient for keeping the device running and the screen on. If the checkbox is cleared I release the request.

function applyPowerPolicy() {
	if(!tizen) { return; }
	var screenPolicy = localStorage.getItem('screenPower');
	if (screenPolicy === null) {
		screenPolicy = 'SCREEN_NORMAL';		
	}
	
	console.log(screenPolicy);
	if(screenPolicy === "SCREEN_NORMAL") 
		{ tizen.power.request("SCREEN", "SCREEN_NORMAL"); }
	else
		{ tizen.power.release("SCREEN"); }
}

function setPowerPolicy() {	
	var isChecked = $("keepScreenOn").is(':checked');
	var policy = isChecked ? "SCREEN_NORMAL" : "";
	localStorage.setItem('screenPower', policy);
	applyPowerPolicy();
}

Other Implementation Details

The other details of how the standalone Speedometer application works can be found in the CodeProject article. Be sure to check it out. I've opened a Samsung Seller application and plan to post the application in their store once it passes certification. I plan to write about my experience once I get through the process.

Tizen and the Samsung Developer's Conference

I've had the original Galaxy Gear since last year. When it was first released it used Android as it's operating system (And not Android Wear, that wasn't available at the time). Earlier this year Samsung decided to make Tizen the main operating system of it's watches. Tizen is an operating system derived from Samsung's Bada and some other efforts that Intel and others had underway.

The current climate in which it is being released is interesting. Google has released Android TV as their solution for the living room. Samsung and Apple have both released car solutions. Some televisions already suuort a series of applications for connecting to services, and the most dominant mobile operating systems are Android and iOS. In this environment Samsung is releasing an operating system to compete for market share across all of these fronts; the living room, car infotainment systems, portable mobile devices, set-top boxes, and more are the target device types that Tizen is aimed for. I might be pessimistic were it another company releasing a new operating system but I'm expecting better outcome from Samsung.

This week Samsung is releasing the Galaxy Gear S in the USA. This is the first Tizen devices with data connectivity. A few days later from the 11-13 November at the Moscone Conference Center (San Francisco) Samsung is hosting a developers conference covering Tizen and development for the Watch and the Tizen powered Televisions (among other topics, such as the SmartThings platform). I plan to be there. I've already started to look into Tizen and made my first Hello World program of types. The details of it can be viewed over at The Code Project.

Tizen Speedometer

From working with this first project and seeing the number of web standards that the HTML side of the development story is based on I can see it seems to be an easy platform to jump into. Those that have already been doing mobile application development with HTML will be able to start development with little effort compared to starting other platforms. Getting started is easy. Though some amount of additional effort will be needed when thinking of how tasks are divided between a phone application and a watch application; applications on the Gear S can run independently of the phone or in conjunction with an application on the phone.

Astrophotography with Windows Phone Part 1: The Hardware Interface

Warning in this post I'm interfacing my telescope to a custom circuit. While I am totally comfortable doing this myself do so at your own risk. The CGEM mounts sell for well over 1,000 USD. If you try to follow what I did and burn out your telescope's mout you are on your own. 

If you haven't already I encourage you to check out my previous post to get the full context of what this post is about. To summarize I'm making a solution for controlling my telescope from my Windows Phone and this post describes the hardware interface.  The phone is going to communicate with the telescope over Bluetooth. The Bluetooth tranceiver from the post on controlling the car with the phone is being repurposed in this post. I'm constructing this circuit on a breadboard. If you would like to follow along with this project but don't want to assemble a bluetooth/serial adapter yourself a fully assembled circuit can be purchased at online retailers such as Amazon.com for 50-80 USD. I've not used these receivers myself and can't provide any information on changing settings on them.

For those familiar with my telescope you may also be aware of a Wi-Fi adapter sold under the name SkyQ Link. Why am I not using it? The reason is simple, there is no information available on interacting with the SkyQ. It seems to be exclusively used by Celestron applications. 

The telescope uses a serial communications standard known as RS-232 for communicating with a computer. The SkyQ Link, GPS receiver, and other accessories communicate with the telescope's mount through one of it's many serial ports.Not all of these serial ports are the same and use different voltage levels. The 6 conductor RJ-12 jacks tend to use TTL voltage levels. The jack on the bottom of the telescope's hand controller uses RS-232.  The RS-232 standard (Created in the 1960s) defines voltages levels, timing, and some other details. To convert the output from the bluetooth tranceiver to levels that the telescop's serial port expects the MAX 232 chip is being used. Celestron ships a 4 conductor RJ-22 to 9-pin D cable that comes with the telescope for interfacing to a computer. This is the connection that we'll be using. 

The circuit is composed of 3 major components; the Bluetooth transceiver, the RS-232 adapter, and a power regulator. The power regulator is somewhat optional. The other two components will run off of any voltage between 3.3 volts and 5 volts. So 3 battery cells would meet needs. But by using a power supply I'm opening up the possibility of other power supplies. The power regulator (known as a 7805 regulator) produces an output voltage that is at least 1.7 volts lower than the input, but not more than 5 volts. If it receives a 5 volt input the 1.7 volt drop will put the output at 3.3 volts which is within toleration of what it needed. If the input voltage is 6.7 volts or higher the 7805 outputs 5 volts and burns off the extra energy as heat. In general you can put up to 12 volts through the 7805. Higher voltages are possible, but they may require a heat sink or additional cooling to prevent overheating. 

 

Powered by a cell phone charger that I received the last time I met with the Windows Phone team at Microsoft (Thanks Desiree!). Because of the voltage regulator there are many other power source options that you could use such as a 9 volt battery. With the extremely simple hardware construction done we can start the first part of communication with the telescope. For now we are only going to be concerned with retrieving state information from the telescope. 

To make sure the circit works I wrote some throw-away code to communicate with the telescope mount. This code is not going to tell the mount to do anything; there's some math that we need to cover before we start to do that. Instead we will query the telescope's current state. I'll ask it for the time, whether or not it's aligned, and the model number. I've made an enumerated type to represent commands. These commands can be queued up to be executed. I also made a few bindable properties to hold the state information.

public enum Command
{
    Nop,
    GetModel,
    IsAlignmentComplete,
    IsGotoInProgress,
    GetVersion,
    GetYear,
    GetDate,
    GetTime,
    GetLongitude,
    GetLatitude,            
};

Command _currentCommand = Command.Nop;
Queue _commandQueue = new Queue();

DateTimeOffset _mountDate = DateTimeOffset.MinValue;
public DateTimeOffset MountDate
{
    get { return _mountDate; }
    set
    {
        if(value!=_mountDate)
        {
            _mountDate = value;
            RaisePropertyChanged("MountDate");
        }
    }
}

string _mountModel;
public string MountModel
{
    get { return _mountModel; }
    set
    {
        if(_mountModel!=value)
        {
            _mountModel = value;
            RaisePropertyChanged("MountModel");
        }
    }
}

bool _isAlignmentComplete;
public bool IsAlignmentComplete
{
    get { return _isAlignmentComplete; }
    set
    {
        if(_isAlignmentComplete!=value)
        {
            _isAlignmentComplete = value;
            RaisePropertyChanged("IsAlignmentComplete");
        }
    }
}

These commands are dequeued one at a time, sent to the telescope, the response is processed, then on to the next command.

void SendNextCommand()
{

    if(_commandQueue.Count>0)
    {
        _currentCommand= _commandQueue.Dequeue();
        switch (_currentCommand)
        {
            case Command.GetModel:
                Write("m");
                break;
            case Command.GetTime:
                Write("h");
                break;
            case Command.IsAlignmentComplete: Write("J");
                break;
        }
    }
}

The telescope doesn't necessarily send the response back in a single chunk. This means that I will need to accumulate the responses until I have enough to assemble a complete response from the parts received.

async private void WaitForData(StreamSocket socket)
{
    try
    {
        byte[] bytes = new byte[128];
        await socket.InputStream.ReadAsync(bytes.AsBuffer(), (uint)bytes.Length, InputStreamOptions.Partial);
        bytes = bytes.TakeWhile((v, index) => bytes.Skip(index).Any(w => w != 0x00)).ToArray();
        System.Buffer.BlockCopy(
            bytes, 0, _responseBuffer, _responseBufferPosition, 
            Math.Min(bytes.Length, _responseBuffer.Length-_responseBufferPosition)
        );
        _responseBufferPosition += bytes.Length;
                
        //If we wanted to do any preprocessing with the message this is the place to do it. 
        //I've currently got no preprocessing needs, so I'm just passing it on to whoever
        //may be listening. 
        OnMessageReceived(bytes);
        ProcessResponse();
    }
    catch
    {
    }
    finally
    {
        WaitForData(socket);
    }
}

void ProcessResponse()
{
    byte delimiter  = 0x23;//#
    int delimiterPosition = -1;
    for(int i=0;i<_responseBufferPosition;++i)
    {
        if (_responseBuffer[i] == (byte)delimiter)
        {
            delimiterPosition = i;
            break;
        }
    }
    if(delimiterPosition>-1)
    {
        //copy out the message
        byte[] response = new byte[delimiterPosition];
        System.Buffer.BlockCopy(_responseBuffer,0,response,0,delimiterPosition);
        //shift the data in the response buffer
        System.Buffer.BlockCopy(_responseBuffer,delimiterPosition+1,_responseBuffer,0,_responseBuffer.Length -( delimiterPosition+1));
        _responseBufferPosition -= delimiterPosition+1;

        switch(_currentCommand)
        {
            case Command.GetModel: ProcessGetModel(response);break;
            case Command.IsAlignmentComplete: ProcessIsAlignmentComplete(response); break;
            case Command.GetTime: ProcessGetTime(response); break;
            default: break;
        }
        SendNextCommand();
    }
}

A different method is defined to process each type of response that comes back. I originally thought about returning the responses as strings. But many of the responses are not composed of printable characters. So I've left the responses as byte arrays.

void ProcessGetModel(byte[] response)
{
    if(response.Length==1)
    {
        switch(response[0])
        {
            case 1: MountModel = "GPS Series"; break;
            case 3: MountModel = "i-Series"; break;
            case 4: MountModel = "i-Series SE"; break;
            case 5: MountModel = "CGE"; break;
            case 6: MountModel = "Advanced GT"; break;
            case 7: MountModel = "SLT"; break;
            case 9: MountModel = "CPC"; break;
            case 10: MountModel = "GT"; break;
            case 11: MountModel = "4/5 SE"; break;
            case 12: MountModel = "6/8 SE"; break;
            case 14: MountModel = "CGEM?"; break; //Need to find documentation to back this up
        }
    }
}
void ProcessIsAlignmentComplete(byte[] response)
{
    if(response.Length==1)
    {
        IsAlignmentComplete = (response[0] > 0);
    }
    else
    {
        IsAlignmentComplete = false;
    }
}

void ProcessGetTime(byte[] response)
{
    if((response.Length==8))
    {
        int hour = response[0];
        int minutes = response[1];
        int seconds = response[2];
        int month = response[3];
        int day = response[4];
        int year = 2000 + response[5];
        int gmtOffset = (response[6] < 128) ? response[6] : 256 - response[6];
        bool daylightSavings = (response[7] != 0);

        DateTimeOffset dateTime = new DateTimeOffset(
            year, month, day, hour, minutes, seconds,  TimeSpan.FromHours(gmtOffset + (daylightSavings?-1:0))
         );
        MountDate = dateTime;

    }
}

I started a program that queued up and executed commands. The responses were pleasing.  When I first started the program I had forgotten to align the telescope. I was trying to figure out what was wrong before I realized the response was correct. I aligned the telescope and started to get back the expected response. The date returned was also correct. For the telescope mount model I got back an unexpected result. For my telescope the response was the byte value 14. The protocol document tha tI have from Celestron doesn't list a value for 14. But the document that I've got also doesn't mention my model. So it appears the document simply has not been updated to account for my telescope. This is fine and an important learning experience; it's possible that the code could one day run against a telescope mount that hasn't yet been created. 

Now that I've successfully been able to communicate with the telescope mount it's time to talk about the math behind what needs to be done. I'll detail most of the math in my next entry.  If you want to follow along a good place to start is learning about Sidereal time. It's going to be a foundational piece of information for what I plan to do. 

 

 

Astrophotography with Windows Phone Part 0 : Introduction

Last week I did a post on using a Windows Phone to control an RC car. I'm applying some of the information in that post to another project. You may have seen one of the astronomy applications that let's some one point their phone at the sky and identify a star or planet with it. I'm making the same type of application with the diference being that the one I'm making will also be controlling a telescope mount. The communication between the phone and the mount will occur over the same Bluetooth Tranceiver that I made iin the post about the car. The first iteration of this project will omit the Arduino. Telescope mounts from Celestron and Meade already contain microcontrollers so I'll start off by communicatin with what is built into the mount. At a later point I will need to reintroduce the Arduino to control other hardware (such as a camera). 

This project a targeting a special audiance; those interested in astronomy that already have a telescope with a computerized mount. Telescopes like this tend to be rather pricy. If you don't already have one I would not suggest picking up a telescope for the sake of experimenting with this project. Some of the less expensive telescops are available for around 500 USD. I'm using the CGEM 800 which at the time of this writing cost about 4 times more than that. For those that already have a computerized telescope if your telescope is another name brand (such as Meade) then you'll need to make adjustments to the code for the protocol that your telescope uses. The telescope that I'm using is on a right ascension mount. If yours is not you will also need to make adjustments to convert right ascension coordinates to altitude-azimuth coordinates. Once again I will be covering the math for this, but I don't have an alt-az telescope for testing. 

In the next post I'll introduce the hardware used to allow the Windows Phone and the Telescope to communicate with each other. A simple program will be introduced that will read and display telescope state; it won't control anything. In the next post after this I discuss the math of what needs to be done. The heavy lifting will all be explained here. After discussing all the math that is needed the third post will present the code in which the phone takes control of the telescope. 

There are also a few things that I won't be covering here. For this program I will only be tracking objects outside of our solar system. The sun and planets will be left out of this program. Unlike the non-solar stars the planets have this habit of wandering around the celestial sphere. They also influence each other's paths (especially Jupiter).  A discussion of the movement of the planets is worthy of it's own series of post. 

Next time: Astrophotography with Windows Phone Part 1: The Hardware Interface

Controlling an RC car with a Windows Phone

Introduction

RCCarCode.zip (2.36 mb)

alt download site

Earlier in the 2013 year while working with the Emerging Experiences group at Razorfish I had the opportunity to do some work with the Netduino, Arduino, and several other technologies that seem to play a significant role in the Maker Movement. Among other things I had converted an RC car to be controlled over Bluetooth with a Windows Phone. A few months ago someone saw a video of the car and asked me how I did it. The comments section on a video wasn't large enough to contain what I thought to be a sufficient response, so I'm writing this article instead.

Recognizing that there's a spectrum of backgrounds and experience levels that one may have when approaching this I've decided to start over from square one and make some changes along the way. The original RC to Bluetooth conversion was done with a Netduino Plus 2. This time around I will be using the Arduino because it is more ubiquitous and generally less expensive. For this revision of the car I'm staying away from the other improvements that could be added for the sake of simplicity. I'm also keeping my focus narrow and staying on the path to get the car up and running. Right now the goal is to cover what is minimally sufficient to get the car running with an understanding of what is going on. In later writings I plan to make improvements on the UI of the control application and add more capabilities to the car.

Prerequisites

To understand this article you'll need to have an understanding of basic digital electronics and programming. You don't need to know or remember the difference between CMOS and TTL gates to understand whats being written here. I'm staying as basic as I can. You will want to have familiarity with one of the C based languages (C, C++, C#) to understand what is being written within this article. I'm using Windows Phone 8 for this first revision of the article but I may return to add Android and iOS in later revisions.

What is the Arduino

I'm going to borrow from a description of the Arduino that I gave before. The Arduino is a single board computer based on the 32-bit Amtel ARM processor. The development environment for it is free (C++ based) It has the support of a large community of hardware and software developers ranging from professionals to hobbiest. From the software side there’s a number of existing solution components that are included in the development software or are available for download. From the hardware side you’ll find a wide range of hardware additions and accessories that can be added to a solution by plugging them into the Arduino.

While there are several forms that are recognizable as an Arduino there are new variants being released be various companies and individuals all the time. Information on constructing them is readily available and the required parts are easily acquired. Most of the Arduinos available available preconstructed will take on a common form and have a name that indicates it's configuration. To avoid the inundating number a variants in the Arduino I'm going to only consider Arduino boards that are available through The Arduino site at the time of this writing.

Any of these can be called an Arduino

How is one Arduino Different from Another?

Just as PCs are available with different configurations (different amounts of storage, ports, so on) so are Arduinos. The differences tend to be in processor speed, the number of different types of ports, or other peripherials. Here are some of the hardware components that may be on an Arduino. Note that note all Arduinos will have all of these available. You can find a table of some of the available Arduino configurations on the Arduino site.

Input/Output Voltages

Many of the peripherals that you connect to are going to expect (or produce) input and output signals that are either 3.3 volts or 5 volts. Some devices can work either either, some cannot. So you'll want to make sure that the Arduino that you use is mated with peripherals that have agreable signal voltages. Some Arduinos will have a switch that will let you change whether it is operating in the 3.3 volt range or the 5.5 volt range. If you want to interface two devices that operate on different voltages without risking damage additional circuits will be needed.

The Seeeduino Arduino Mega Adk that I'm using runs in 3.3V or 5V mode. But I must remember to ensure the switch is set to the needed voltage.

Processor Clock Rates

The Arduino boards available presently range in speed from 8 MHz up to 84 MHz. 16 MHz is the most typical.

USB Ports

Most of the Arduino boards have a USB port for programming and for getting information back from the Arduino. When connected to your computer it will appear as another Serial port. So you could use any terminal software that uses a serial port for interacting with the Arduino. Some of the Arduinos can emulate other devices such as keyboards or mice. Some Arduinos also have a USB host port that will allow it to interact with other USB peripherals.

Digital Port

Quickly glancing at the Arduinos that I have on my desk right now the number of ports that they have range from a little more than 5 to a little under 50. The digital ports can act as both outputs or inputs. When running in output mode they can programmatically be set to either a high or low voltage. When operating as an input a program can see if something connected to the Arduino is outputting a high or a low voltage. This extremely basic ability is an important building block for other capabilities. Turning on a light or motor or even communicating with other devices can be done with basic operations over a digital port. Some of the digital ports also support interrupts. So you could associate that port with a routine that automatically gets called if the ports status changes.

Analog Port

If you need to set a pin's output to something between high and low then the analog port is what you'll want to use. This can be used to control the speed of a motor instead of turning it on or off, or to control the brightness of a light. When used as an input an analog port can be used to detect the position of a potentiometer or the intensity of light on a sensor .

PWM Port

The PWM ports are able to output square waves. In general the signals outputted on these ports will all have the same frequency. But the pulse width of the wave can be varied. The following two waves have the same frequency but the widths of the waves differ.

The percentage of time that the wave spends in its high state is also called the wave's duty cycle. When a PWM signal has a 0% duty cycle it is always off. When it has a 100% duty cycle it is always on. PWM signals can be used to control the speed of a motor or the brightness of a lights.

Communications Port

While it's possible to communicate with other hardware through careful timing of turning a port on and off you will generally not want to (or need to) do this yourself. The Arduino supports some of the standard communications protocols used by many other circuits and sensors that you may want to interact with. All of these communications ports work serially; they will send or receive a message one bit at a time.

  • Serial Port - Connects a single device to another. Uses two lines for communication, one for sending, another for receiving. Devices that use these ports will have a set speed at which they can send and receive bits (baud rate). Two devices connected with a serial port must agree on the speed at which they will transmit information (baud rate, ranging from 300 baud to 57600 baud) and how a sequesnce is to be terminated (number of stop bits). Devices using serial port communication are able to track time passed so that they can write to or read from the communications lines at the correct rate. Serial ports on an Arduino can either be implemented through hardware or software. Only specific pins can be used for hardware serial ports, but any two pins can be used for the software serial port. However the software serial port cannot send and receive at the same time while the hardware serial ports can.
  • I2C - Connects a device to multiple other devices. Like the serial port the I2C port uses two lines from the Arduino. But unlike the serial port (which connects the arduino to only one other device) the I2C lines can be connected to multiple devices. Each device connect to the I2C ports has an address. When interacting with one of the devices the Arduino must send the address of the device that it wishes to respond and only that device will respond. An I2C address is composed of either 7 or 10 bits. So either 128 or 1024 devices could be connected to an I2C lines. Timing for communication is controlled through a clock line (usually labeled SCL) and data, whether transmitted or received, travels over a single data line (labeled SDA). Unlike the Serial Port (which allows data to travel in both directions at the same time) I2C communication is one direction at a time. But the I2C bus speed on an Arduino is at 100 KHz.
  • SPI - connects one device to multiple othe rdevices. SPI communication uses four lines; one for clock synchronization, one for data from the master device, one for all the devices that may respond, and a device selection line. Instead of transmitting an address the selection line for the device that is to respond must be driven high (each device will have its own line). The speed of the SPI bus is going to depend on the clock speed of the Arduino and a clock divider value (possible values will depend on the Arduino board being used). The default values on most Arduinos will result in a communications rate of 4 MHz.

What peripherals are Available for the Arduino

You can connect Arudinos to a wide range of products even if those products were not designed with the Arduino in mind. Your ability to do that is going to depend on your knowledge level with the Arduino. But what of the products that were made with the Arduino in mind or can be interfaced with litter effort? There are a number of products that can be used by aligning some pins and stacking them on top of the Arduino. Peripherals like this are referred to as "shields."

  • Wi-Fi and Ethernet Shields - host and consume simple web services or control your project over a network ( 1,2 )
  • GPRS Radio - have your circuite send text messages, make and receive calls, or access the Internet on the go (1)
  • Memory Shields - Read from and write to memory cards (a)
  • Bluetooth - One of the many ways that you can communicate with the Arduino wirelessly. One of the best options for devices controled by other mobile devices. (1).

There are other devices that while not made with the Arduino in mind interface to it with little effort because they implement a simple or common interface

  • Bluetooth
  • Servos
  • Relays
  • LCD Displays

Getting Started

Let's start working towards a "hello world". For the Arduino this will mean using it to turn on a light. You'll need the following

  • Computer (PC, Mac, Linux) with a free USB port
  • An Arduino board
  • Light emiting Diode
  • Resistor (about 220 Ohms)
  • Arduino IDE

Software Installation

The software is available for Linux, OS X, and Windows. I'm using the Windowa version which can be installed in one of two ways. The method I would suggest is downloading the "installer" version of the download. Like many other Windows installations the only thing the installer requires you to do is click on a "next" button a few times. The Zip version of the download will let you unzip the IDE to the arbitrary place of your choosing. After the installation has completed connect the Arduino board to your computer with a USB cable. Arduino's usually ship with a program preloaded that blinks a light on the board. Once plugged into the USB you should see the light on the Arduino strt to blink and the drivers should install.

It's possible that you might not be prompted for the drivers. I've connected the Arduino Mega to my computer and it wasn't recognized (unlike the other Arduinos it uses a different hardware component for it's connection). It originally showed up in the device manager as an unrecognized device. The drivers  can be found in the Arduino application folder. 

 

 

Creating a New Program

Start the Arduino IDE. By default the Arduino IDE will open blank and ready for you to start writing code. If you wanted to start another blank project selecting New from the File menu will open a new instance of the IDE. If you are using version 1.5.5 of the IDE (a beta at the time of this writing) then the window will open with two empty functions defined. If not then the window will be completely blank. If it's blank trype the following code.

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

We are going to compile this code and upload it to the board. We'll need to tell the IDE what board that we have and which com port that it's attached to. Under the Tools menu there is a Board submenu that contains the Arduino Board models supported by the IDE. Select the board name that matches yours. You'll need to do the same thing for the port. If you don't know which port your Arduino is using unplug it and access the menu again to see which port name has disappeared from the listing. The one that has been removed is the one that your Arduino board is using.

In the toolbar there is a button that you can use to check to code for syntax errors (a check mark) and a button that can be used to upload the compiled program to the Arduino (an arrow).

Click on the arrow. If all goes well at the bottom of the IDE you will receive a message that says "Upload Successful" and the light should stop blinking. Let's update the program so that we can blink the light ourselves. To do this we need to configure a pin as an output pin. Many times you can use the same pins across different Arduino boards. It's a good practive to define the pins being used in a #define section or as a variable instead of using the literal pin number. If it never needs to be changed then it can be changed in one place. Pin 13 is usually connected to a led. Writing a HIGH value to it will turn the led on. So let's defined the pint that we are using to control the light as 13.

#define LIGHT_PIN 13

Then we write a HIGH or LOW value to it. Initialization steps are done in the setup function. Pin 13 could either be an input or output pin. We need to set it as an output pin using the pinMode function. When the device first starts (or is restart) it first runs the code in the setup() function. It will then run the code in the loop function until the device is turned off. In the loop we want to turn the light on, wait for a second (1000 ms), turn the light off, and then wait for another second.

#define LIGHT_PIN 13

void setup() {
    //set PIN 13 as a pin that we can write to
    pinMode(LIGHT_PIN, OUTPUT); 
}

void loop() {
    digitalWrite(LIGHT_PIN, HIGH);
    delay(1000);
    digitalWrite(LIGHT_PIN, LOW);
    delay(1000);
}

Deploy the application again. After a few seconds the light should start to blink. Congradulations! You've completed your first Arduino program. Before moving on let's make a small change. Instead of just turning it on and off let's adjust the brightness so that it fades in and out. For this we'll need to start adding external circuitry. For this next part you'll need a LED (light emitting diode), a resistor with a value in the range of 300 Ω to 1 KΩ value, and a breadboard. The resistor is for lowering the current that goes through the LED to ensure that we don't burn anything out with too much current. We are going to adjust the brightness of a led by using the analogWrite() function to change the amount of power supplied to the ligh. Pin 13 on many Arduinos doesn't support the analogWrite() function.

You need to look up which pins on the Arduino that you are using can be used for PWM output. Go to the Arduino Products Page and click on the model for the Arduino that matches the one you have. On the page that opens search the page for "Input and Output" and look for the line in that section about PWM. The pin numbers that you can use will be listed there. Below is the information for some of the arduino boards

Board Model Available Pins Resolution
Arduino Uno 3, 5, 6, 9, 10, and 11 8 bit
Due 2-13 8-12 bit
Mega ADK/Mega 2560 2-13, 44-46 8-bit
Yún 3, 5, 6, 9, 10, 11, and 13 8 bit
Nano 3, 5, 6, 9, 10, 11 8 bit
See analogWriteResolution() for information on changing resolution.

About using a Bread Board

If you've used a bread boardbefore you can skip this section. Breadboards allow you to prototype a circuit more quickly and reduce the amount of wires that you would need to construct the same circuite without a breadboard. Underneath the holes in the breadboard are conductors that electrically connect components. The The conductors all run paralle to each other and are usually perpendicular to the length of the breadboard. The exception being the powerlines which run down the length of the board. There's a depression down the center of  the board. The conductors do not cross this depression. Any components that are inserted on the same row (the rows are numbered) that are on the same side of the depression are connected. jumper wires need to be plugged in to connect components that are not on the same row and the same side of the divide.

Closeup of a breadboard. The red outline mars sets of holes that have a common conductor underneath.

Wiring the LED to the Arduino

LEDs will only work if current passes through them in the correct direction. There are two wires on the LED that are of different length. The longer of the two wires must be connected to a positive source while the shorter to a negative. Use a jumper to connect one of the pins labeled GND  to a row of wires on the bread board. Plug the LED into the board so that the shorter wire is in the same row as the GND wire. Connect the resistor into the board so that one of the wires is in the same row as the long wire of the LED and the other end is in an unoccupied row of the breadboard. Using a second jumper wire to connect the other end of the resistor to the pin that you are using for PWM.

Analog Code

Once the circuit is wired we can write the code to control the brightness of the led. When we wrote the previous program it was necessary to use use pinMode to set the pin to output mode before controlling it. It isn't necessary to do this when using analogWrite on a pin. We'll use the PWM port in 8-bit mode (which is much more widely supported than 10-bit mode). The variable containing the value to be written to the pin is going to start at 0, count up to 255, and then back down to zero. Each new value will be sent to the PWM pin. The result is that the LED will grow bright and then dim in cycles.

//Change the following to the pin number that
//matches the one that you are using. 

#define LIGHT_PIN 13

int brightness = 0;
int delta = 1;


void setup() {
}

void loop() {
    analogWrite(LIGHT_PIN, brightness);    
    brightness+= delta;
    if(brightness == 255)
      delta = -1;
    else if(brightness == 0)
      delta = 1;    
    delay(10);
}

Input and Output with the Serial Port

The serial port can be used to communicate with peripherals connected to the Arduino or to communicate back to the computer. There will be 1 to 4 hardware serial ports on your Arduino board. They will be named Serial, Serial1, Serial2, and Serial3. Each of these ports (if present in Arduino board) will be assigned to specific sets of pins. You can also instantiate software serial ports. Software serial ports can be assigned to any two pins. The hardware and software serial ports appear similar in capabilities. But the software serial port can only send or receive at any given point in time but can't do both simultaniously. The hardware serial serial port can do both at the same time.

The port Serial is connected to the computer. Communication between your computer and the Arduino occurs through this port when your programs are uploaded to the Arduino. You can also make your own applications on a computer that interact with a connected Arduino by opening the appropriate port. The computer and the Arduino will need to agree on a baud rate (data transfer speed).

Method Description
int available() Gets the number of bytes available for reading
void begin(baudRate) Sets the baud rate for the serial port and opens it for reading and writing.
void print(value) closes the port and disables the pins for communication.
void print(value) Writes a string to the port. Numbers and floats printed to the port will be converted to strings first.
char read() reads a byte from the serial port
readBytes(buffer, length) Reads characters from the serial port into a buffer
void write(byte) Writes a byte value to the serial port

The Arduino IDE has an interface called the Serial Monitor (can be opened by pressing CTRL+Shift+M or from the menu path Tools->Serial Monitor) that can be used to see the values coming back from the serial port or being written to it. For a simple demonstration we'll have the arduino count from one to one hundred and output it to the serial port.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  for(int i=0;i<=100;++i)
  {
    Serial.println(i);    
    delay(100);
  }
}

After you upload the program open the serial port monitor. You'll see the stream of numbers coming back.  Here I want to point out that there's a difference in behavior in how the Arduino Yun, Micro  and Arduingo Leonardo behave when compared to the other Arduinos. Many of the other Arduinos use a chip that is separate from the main processor for handling communication between the computer and the Arduino's processor. When you open the Serial Port Monitor on these boards the device will reset. So you'll be able to catch all of the information that the devices outputs from begining to end. On the Leonardo, Micro and the Yun the serial communication is not being handled by a separate chip. The Amtega processor in these devices have a built in USB interface that presents itself as a serial port and can also present itself as a mouse, mouse, and serial port. While the serial connection can remain open on the other devices when they are reset if the processor is reset on the Yun, Mico, or Leonardo the virtual serial port would disappear while it restarts and the computer's connection to it will be lost. So these devices do not reset when you open a serial connection from your computer and the first few numbers that are written will not show up in the serial monitor. You could have the processor wait until the serial port is open before it starts writing numbers with a slight modification to the program. The statement if(Serial) wrapped around the code we just wrote to prevent it from executing until the serial port is open.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  if(Serial)
  {
    for(int i=0;i<=100;++i)
    {
      Serial.println(i);  
    delay(200);  
    }
  }
}

All the programs we have done until now have been non-interactive. We are about to do our first interactive program. In this one the Arduino will listen for text to come in over the serial port and will turn the light on or off in response to it. The program will also send a small bit of feedback on what it's doing. In the updated program the delta variable is going to default to zero. So the light's brightness will not start changing as soon as the program starts up. Instead when this program received the character '1' on the Serial object it will change delta to one so that the brightness will grow until it reaches its maximum value (then delta is reset back to 0 to prevent the brightness level from changing). When the program receives the value '0' it will set delta to -1 until the brightness variable reaches its minimum value. All other characters received through the Serial object will be ignored. When the program does receive a value that it's processing it will print back a message that will show up on the computer. Here is the source code to the updated program.

#define LIGHT_PIN 13

int brightness = 0;
int delta = 0;


void setup() {
  Serial.begin(9600);
}

void loop() {
    if(Serial.available())
    {
      char c = Serial.read();
      if((c == '1')&&(brightness!=255))
      {
        delta = 1;
        Serial.println("Turning Light On");
      }
      else if((c=='0')&&(brightness!=0))
      {
        delta = -1;
        Serial.println("Turning Light Off");
      }
    }
    brightness+= delta;
    analogWrite(LIGHT_PIN, brightness);    

    if(brightness == 255)
      delta = 0;
    else if(brightness == 0)
      delta = 0;    
    delay(10);
}

Run the program and open the Serial Port Monitor. From the monitor type the value 1 and press enter. You'll receive a confirmation back and will see the light's brightness begin to grow. Send it a 0 and you'll see the light's brightness diminish until it's extinguished.

Servos

There is only one more concept to cover before we are ready to interface to the car. And that is the concept of the servo. Servo is short for servomechanism. The term can refer to any device that uses negative feedback to correct its performance in achieving its built in function. Most of the time when some one mentions a servo in the context of an Arduino the person is refering to a servomotor. Servomotors receive a signal that coresponds to a desired position. The servo will rotate its shaft until the desired position is reached and will hold its position. RC (Remote Control) servos receive the position signal as a PWM signal. While you could directly send the PWM value for a desired position using analogWrite it is usually easier to use the <Servo.h> library instead. It will take care of the mappings between the angular position that we want and the value that would need to be sent through analogWrite() for that position. Just as analogWrite() will only work on certain ports the <Servo.h> library will only work on certain ports. Also note that with the exception of the the Arduino Mega use of the <Servo.h> library will disable the use of analogWrite() on ports 9 and 10, even if you are not using those ports to control a servo.

Method Description
void attach(pin, [max, min]) Attach the servo variable to a pin. One of the overloaded versions of this method can be used to adjust the minimum and maximum pulse width.
void write(angle) Writes a value to the servo setting the shaft position accordingly.
int read() Returns the last value written to the servo.
void detach() Detaches the servo object from the pin.

RC servos have three wires. Two of the wires will be for power. A red wire must be connected to a positive power source and the black or brown wire must be connected to the ground (GND). The third wire is connected to the PWM source. If you are going to drive several motors you will want to have the motors connected to a power source that can handle enough current. But we can connect a small servo to the Arduino without much concern.

This program will be much like the previous one. Only instead of controlling brightness we will be controlling the position of the motor. Servos generally have a range of 180 degrees. The minimum value is 0, the maximum value is 180, and middle value is 90. The exact range of your servo may vary. Don't try to drive the servo past its physical limit. Doing so can cause the servo to overheat. Confession: I burned out somewhat expensive servo this way when I was first programming with on.

In the previous program I used a delta variable to increment or decrement the brightness value. While you could do this for the Servo it is not necessary unless you need to control the rate of the turn. For light brightness jumping from one value to another will result in what looks like a simultanious change in brightness. The servo moves at a limited speed. Jumping from one value to another will result in in the servo changing position over time. There's no instantanious transition in position. So in this program we will not worry about incrementing the position over time and will just jump to the position that we need. Because there are positions between absolute left and absolute right in which we will have interest this program will respond to values between 0-9 instead of just 0 and 1.

//Change the following to the pin number that
//matches the one that you are using. 
#include <Servo.h>

#define MOTOR_PIN 13

Servo steeringServo;

void setup() {
  Serial.begin(9600);
  steeringServo.attach(MOTOR_PIN);
}

void loop() {
  if(Serial.available())
  {
    char c = Serial.read();
    switch(c)
    {
      case '0': steeringServo.write(0); break;
      case '1': steeringServo.write(20); break;
      case '2': steeringServo.write(40); break;
      case '3': steeringServo.write(60); break;
      case '4': steeringServo.write(80); break;
      case '5': steeringServo.write(100); break;
      case '6': steeringServo.write(120); break;
      case '7': steeringServo.write(140); break;
      case '8': steeringServo.write(160); break;
      case '9': steeringServo.write(180); break;      
      default:
      break;
    }
  }
  else
    delay(100);
}

Connect a servo to your Arduino. The red wire should be connected to the pin labeled 5V and the black/brown wire should be connected to one of the pins labeled GND. The remaining wire is to be connected to the PWM pin that you are using. Run the program and open the serial monitor. As you are sending the values keep an eye on your servo to ensure it's not trying to go past it's physical range. If it does immediately return it back to a position that is within its range.

Controlling the Drive Motor

Something to keep in mind before you start activating the drive motor on your vehicle. Make sure you lift the drive wheels so that they are not touching anything. Last thing you'd want to happen is for the car to take off at full speed while it's still connected to your computer or on a desk. Depending on your car you may be able to do this by turning it upside down. I took some camera rig parts that I had laying around and assembled them to support the vehicle.

RC car supported by camera rig pieces.

The drive motor on the car that I'm uses uses an ESC (Electronic Speed Control) unit. The ESC does a couple of things. It contains a power regulator that's outputting 5 volts from the 7.2 voltage from the battery and it activates the drive motor. The 5 volt output is also routed to the steering servo and the radio receiver/control circuit. We are unplugging the car's receiver and connecting the Arduino in it's place. If we use the same program that we used to control the servo but connect the arduino to the ESC instead of the servo we can use it to control the motor's speed. We are going to wire the two together a little differently this time. The ESC is going to need to be connected to it's own power source (the car's battery). There Arduino would not be able to power the drive motor. For this test you do not need to connect the red wire. If you want to connect the red wire anyway connect it to the VIN pin so that the voltage from the ESC is passed through the Arduino's voltage regulator.

After you are done with the wiring run the program again. This time you should be able to make the car's drive motor go in forward and reverse. If your ESC behaves as mine does if you try to go from forward to reverse without going through the neutral position the ESC will interpret it to mean you want the vehicle to brake. So you may need to select the neutral position before you change directions.

The ESC that I am using is the Dynamite Tazer 15T. Despite documentation that is available on the Internet (PDF) this ESC does not allow any calibration. If you are using another esc calibration may be required so that the esc knows what speeds />directions to map to the range of values that it needs to work with. Since I don't have an ESC that supports calibration I won't be able to address that myself within this document.

The Dynamite Tazer 15T

Bluetooth Communication

There are a number of Bluetooth solutions available that will work with the Arduino. Some are available as shields. I didn't want to use a shield as a solution since it would restrict which pins that I could use for bluetooth communication. I used one that needed to have its pins connected to the arduino individually. Most of these will have 4 connections that you'll care about. Two of them are for power. They will need to be connected to the 5 volt line and the GND. The other two lines are for data to be sent and data received. We are also finally to the point where we are going to make use of the Windows Phone. Before we get started with coding go ahead and connect your power and GND to power it up and pair your phone with it. On the bluetooth device that I'm using the pairing code is 1234. You'll need to check with the documentation for the Bluetooth circuit that you are using to know what code to use.

Picture of the Bluetooth Module that I am using

Picture of the Bluetooth Module that I am using

You'll need to write code that will do a a few things

  1. Get a list of the paired bluetooth devices
  2. Select the paired device to be used for communication
  3. Open streams to the device for listening and sending information

For getting a list of the Bluetooth devices paired with the phone Microsoft has provided the PeerFinder

class. You'll need to add the Proximity permission to your application to use this class. The list of devices paired with the phone can be retrieved with two lines of code.

PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
var pairedDevices = await PeerFinder.FindAllPeersAsync();

For the sake of improving the user's experience you would probably want to give your Bluetooth receiver a distinct name that the application could look for to distinguish it from the other Bluetooth devices. On many of the Bluetooth receivers it's possible to change the name that the device uses. On the one that I have handy I've noticed that the company that produces it seems to have explicitly stricken out the portion of the documentation that explained how to change my adapter's ID (probably appropriate, as the device isn't responding to name change commands). I'm going to stick with the name that seems to be burned into my device, linvor. Check the documentation in your Bluetooth adapter to see what name you need to use.

The pairedDevices collection in the above code will contain PeerInformation instances. Grab the one that represents your device and use it to create a new Socket object. The Socket will be used for reading from and writing to the Bluetooth adapter.

_socket = new StreamSocket();
await _socket.ConnectAsync(_selectedDevice.HostName, "1");

Now we can send and receive messages between the Windows Phone and the car circuit. Read and write operations are asynchronous. Using the InputStream member of the socket we can initiate a read operation. If there is nothing to read the call will [perceivably] wait until there is data available to be read (the nuances of what really goes on while interesting is beyond the scope of this document). Once the bytes are available and read I'm converting them to a string for later processing.

byte[] bytes = new byte[128];
await socket.InputStream.ReadAsync(bytes.AsBuffer(),(uint)bytes.Length, InputStreamOptions.Partial);
bytes = bytes.TakeWhile((v, index) => bytes.Skip(index).Any(w => w != 0x00)).ToArray();
string str = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
OnMessageReceived(str);

For this first iteration of the project the car doesn't need to send back any vital data. It's only going to be listening for instructions for what it should be doing. For now the only instructions to send are of what the state of the throttle and the steering servo should be. I'm sending the commands in strings that look like a REST request.

public void TransmitState()
{
    if ((_communicationController != null)&&(_communicationController.IsConnected))
    {
        _communicationController.Write(String.Format("/car/throttle/{0}\r\n", ThrottleValue));
        _communicationController.Write(String.Format("/car/steering/{0}\r\n", SteeringValue));
    }
}

With that the basics of what need to happen on the Windows Phone side for communicating with the car have been covered. There is still work to on deciding on a user interface in the application. Let's go back to the car to implement the code for responding to the received commands.

Don't Let the Car Get Away!

Since we are approaching a point at which the car is almost prepared to be sat down on the ground to be driven there's something I want to address. You must be prepared to respond to a loss of a connection. If you don't the car could end up continuing to do the last thing that it was doing until it gets a connection again. If the last thing it was doing was going ahead full throttle chances are you won't be able to reestablish a connection without sprinting after the car. There are a couple of solutions that come to mind to handle this. On many of the Bluetooth receivers that I've seen there is an additional line that connects to a led that will change its blinking sequence to indicate whether or not the Bluetooth receiver has a connection. It's possible to connect to this and put the car in a neutral state if it indicates that the Bluetooth connection has dropped. Another method (the one that I will go with) is to keep track of how long it's been since an instruction was received. If more than a certain amount of time passes and no instructions are received stop the car.

The millis() function returns how much time has passed since the Arduino was started in milliseconds. Every time an instruction is received we can save the value returned by this function and use it as a reference for knowing how long it's been since an instruction was received. With each execution of the main loop the the millis() function is called again and compared to the saved value. The difference between the two values is the amount of time passed since the last instruction. Once the difference has become greater than a certain amount we know it's been a while since an instruction was received. The car will be put in a neutral state. If an instruction is received before this condition occurs then the saved value would have been updated so the difference between the saved time value and the current time value would not be great enough to reach the expiration period.

Parsing the Commands

Parsing is easy since all the commands are being sent in what looks like a rest request. Each segment of the path in the REST like request is associated with a method. Each time an instruction is received it is passed to ProcessCommand(string) which will parse out the first segment and use it to decide which method to call next. Right now all of the instructions will start with /car/. The root level method in the processing call stack only checks to see if an instruction starts this way and does nothing if the command is something else.

void ProcessCommand(String command)
{
  int startPosition, endPosition;
  String segment;

  startPosition =  command.indexOf('/', 0);
  endPosition = command.indexOf('/', startPosition+1);
 
  if((startPosition>-1) && (endPosition == -1))
  {
      segment = command.substring(startPosition + 1, endPosition - startPosition+1);
      startPosition = endPosition + 1;
  }
  if(segment == "car")
     ProcessCarCommand(command.substring(endPosition));
}

The ProcessCarCommand() method is similar. It is testing to see if the next part of the instruction is "throttle" or "steering" and called the ProcessThrottle() or ProcessSteering() methods respectively.

void ProcessCarCommand(String command)
{
  int startPosition, endPosition;
  String segment;

  startPosition =  command.indexOf('/', 0);
  endPosition = command.indexOf('/', startPosition+1);

  if((startPosition>-1) && (endPosition>-1))
  {
       segment = command.substring(startPosition + 1, endPosition - startPosition);//.
  }

  if(segment=="throttle")
     ProcessThrottleCommand(command.substring(endPosition));
  else if (segment=="steering")
    ProcessSteeringCommand(command.substring(endPosition));
}

The methods that follow are finally getting to where the rubber meets the road; they are controlling the steering and throttle lines. Their implementation is almost identical. They strip the numeric value off the end of the command (which will be between the values of -1 and 1). The value of 1 for the throttle represents full throttle forward, -1 would be for full reverse, and 0 for neutral. Similarly -1 for the steering is full left, 1 is full right, and 0 is straight ahead. These values are being scaled and shifted before being sent to the Servo object. The continuous value range of -1 to +1 needs to be remapped to the the values 0 to 180. The Arduino function library already contains a function for doing this appropriatenamed map. It takes 5 arguments. The first is the value to be remapped. The next two are the lower and uper range for the value. The fourth and fifth are the range to which the value needs to be mapped. For our specific case the call will look like map(value,-1,1,0,180). The mapped value is then written to the servo object for either the steering or throttle. The code for the two functions follows.

float StringToFloat(String str)
{
  char buf[str.length()];
  str.toCharArray(buf, str.length());
  float retVal = atof(buf);
  return retVal; 
}
void ProcessThrottleCommand(String command)
{
  if(command.length() < 2) return;
                         float newthrottlevalue=StringToFloat(command.substring(1));
                         if ((newthrottlevalue < -1)&&(newThrottleValue > 1))
   return;
   int servoValue =(int) map(newThrottleValue,-1,1,0,180); 
   throttleESC.write( servoValue );
}
void ProcessSteeringCommand(String command)
{
  Serial.println("Processing Steering Command");
  if(command.length() < 2) return;
                         float newsteeringvalue=StringToFloat(command.substring(1));
                         if((newsteeringvalue < -1) && (newSteeringValue > 1))
    return;
  int servoValue = map(newSteeringValue,-1,1,0,180);
  steeringServo.write( servoValue );
}

Control Interface

All the code needed for sending control signals to the car and to have the car interpret and act on them has been presented. I skipped over discussing a user interface for controlling the car though. Some of the other phone controlled systems I've seen use the accelrometer for control. This is a matter of personal preference, but I don't like the accelerometer based approaches. When playing games on my phone the method of control that prefer second is the virtual joystick with a dead zone that is centered on whereever one's finger happen come in contact with the screen. My most preferred method of control is a physical controller.

I made an extremely simple virtual joystick for the phone in the form of a user control. When some one first place their finger down on the control that point becomes the new center point for the dead zone. Sliding ones finger will move the virtual joystick out of the dead zone and be registered as a direction. Lifting one's finger off of the control will set the virtual joystick back to it's neutral position.

Second best isn't bad, but we can do better. I've got a Moga bluetooth game controller that is compatible with Windows Phone. So I've added support for that too. Normally I would have the code organized so that there are a number of logical joysticks (whether physical or virtual) and then some mechanism for deciding which one of the joysticks will be listened to. I'm avoiding that organization in this article for the sake of simplicity. The code handling input from the Moga is in the same class as the virtual joy stick and there's absolutely no resulution implemented for what to do if some one decides to use both the touch screen and the game controller at the same time.

Moga Bluetooth controller.

There's an SDK at Moga's web site that contains an assembly (Moga.Windows.Phone) that simplifies interaction with the Moga controller. There are two modes of interaction with the controller, polling and listening. In polling mode every time the code wants to know the state of the controller it will need to query the controller. In listening mode as the state of the controller changes methods on your code are called through an interface indicating what has changed. Xaml based programs will usually want to use the listening mode while DirectX based programs will use polling. To use listening mode my VirtualJoyStick class implements the IControllerListener interface. More development information on the Moga series of controllers can be found on their site.

IControllerListener methods
Method Description
void OnMotionEvent(MotionEvent e) One of the analog inputs on the controller has changed. This includes both thumb sticks and the the analog triggers.
void OnStateEvent(StateEvent e) Indicates the connection and battery state of the controller.
void OnKeyEvent(KeyEvent e) The pressed state of one of the buttons has changed.

Remember what I said earlier about responding to the potential loss of the connection between the phone and the car? That also applies to the connection between the phone and the game controller. If the connection to the controller drops (battery goes dead, or the user walks away from the phone) the code on the phone needs to be prepared to start transmitting a neutral state. Otherwise the phone will continue to transmit what ever the last known state of the game controller indicated. One of the IControllerListener events is used for this, OnStateEvent(StateEvent e).

public void OnStateEvent(StateEvent e)
{
    if (e.StateKey == ControllerState.Connection)
    {
        if(e.StateValue == ControllerResult.Disconnected)
        {
            SetNeutralState();
        }
    }
}

I've decided to use the left thumb stick for steering and the right thumb stick for the throttle. I'm ignoring the buttons all together.

public void OnMotionEvent(MotionEvent e)
{
    this.Dispatcher.BeginInvoke(() => { 
        if(e.Axis==Axis.Z)
        {
            Y = e.AxisValue;
            OnVirtualJoystickUpdated();
        }
        else if(e.Axis == Axis.X)
        {
            X = e.AxisValue;
            OnVirtualJoystickUpdated();
        }
    });
}

Loose Connections

I've said next to nothing about the physical assembly of the finished product. In part I've done this because it's not my final design. Dependind on the car that you have you may be able to screw the Arduino in place on the vehicle. You are not going to want to use loose wires to connect the servo and ESC to the Arduino though; with just a little bit of strees the wires would come loose. Instead check out your local electronics store or other provider to see what prototype shields are available. Using one of those you may be able to securly hold the connections in place through either soldering or with screws.

What's Next

Writing additional code so that the car can be controlled by an Android phone isn't much effort. The same concepts carry over. When time allows I may update this article or add another one to explain what needs to be done to control the car with an Android phone. Also keep in mind that my personal goal is to make the car more autonomous. This means that the car must be able to know something about it's environment and position. In the next update I plan to walk through the various sensors that will be attached to the car and how to use them. These include GPS, distance sensors, and motion sensors such as an accelerometer and gyrometer/rate sensor. Because of the low distance range on bluetooth radios I'll be using a different radio (Wi-Fi) so that more distance can be put between the phone and the car. I may eventually move up to adding a GSM radio.

Revision History

  • 2014 February 12 - Initial Publication

 

RCCarCode.zip (2.36 mb)

alt download site

Spin wait timer for .Net Micro Framework

I'm working on getting a piece of hardware interfaced to a computer using a Netduino. There are some places in the documentation for this hardware that specify delays for which the available .Net Micro Framework functions just won't work for me. For this application spin waits are fine. So I've implemented a class to take care of the delays for me. When the program is first started I call the calibrate method on this class. Calibrate will perform a spin wait for a predetermined number of cycles timing how long it takes to complete. The amount of time it takes to complete is then used to calculate the ratio between the cycles and the timing. That value is used to know how many cycles to wait to delay for an approximate amount of time. 

I've found that this works perfectly fine for my needs. Something to keep in mind when extremely short delays are needed is that there's some amount of overhead with the function call and preparing for the loop. For many applications this may not matter.  If the spin wait is interrupted (such as by another thread taking control or a hardware interrupt being triggered) then the timing could get thrown off. So this solution isn't for every one.

 

I've pre-populated the variable for cycles per second with the value that the hardware that I am using came up with. The hardware I am using is a Netduino Plus 2. The needed value will likely be different on other hardware and possibly on future firmware updates of the same hardware.

    public class SpinWaitTimer
    {
        double _cyclesPerSecond = 112262.2255516001;

        public double CyclesPerSecond
        {
            get { return _cyclesPerSecond; }
            set { _cyclesPerSecond = value; }
        }

        public SpinWaitTimer()
        {
        }

        public void Calibrate()
        {
            const int CYCLE_COUNT = 1048576;
            int dummyValue = 0;
            DateTime startTime = DateTime.Now;
            for (int i = 0; i < CYCLE_COUNT; ++i)
            {
                ++dummyValue;
            }
            DateTime endTime = DateTime.Now;

            TimeSpan timeDifference = endTime.Subtract(startTime);

            _cyclesPerSecond = ((double)CYCLE_COUNT / (double)timeDifference.Ticks)*10000000d;

        }

        public void WaitSeconds(double sec)
        {
            int cycleCount = (int)((sec * CyclesPerSecond));
            int dummyValue = 0;
            for (int i = 0; i < cycleCount; ++i)
            {
                ++dummyValue;
            }
        }

        public void WaitMilliseconds(double microseconds)
        {
            int cycleCount = (int)(_cyclesPerSecond * CyclesPerSecond / 1000d);
            int dummyValue = 0;
            for (int i = 0; i < cycleCount; ++i)
            {
                ++dummyValue;
            }
        }

        public void WaitMicroseconds(double microseconds)
        {
            int cycleCount = (int)(_cyclesPerSecond * CyclesPerSecond / 1000000d);
            int dummyValue = 0;
            for (int i = 0; i < cycleCount; ++i)
            {
                ++dummyValue;
            }
        }
    }