Nov 5 2014

Tizen and the Samsung Developer's Conference

Category: MobileJoel Ivory Johnson @ 06:11

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.

Tags: , , ,

Mar 9 2014

Astrophotography with Windows Phone Part 1: The Hardware Interface

Category: MobileJoel Ivory Johnson @ 08:49

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. 

 

 

Tags: , ,

Mar 3 2014

Astrophotography with Windows Phone Part 0 : Introduction

Category: Joel Ivory Johnson @ 09:11

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

Tags: ,

Feb 12 2014

Controlling an RC car with a Windows Phone

Category: C# | MobileJoel Ivory Johnson @ 02:47

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

Tags: , ,

Apr 9 2013

Spin wait timer for .Net Micro Framework

Category: Joel Ivory Johnson @ 03:52

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;
            }
        }
    }

Tags: ,

Jan 28 2013

Hello World on the PlayStation® Vita

Category: MobileJoel Ivory Johnson @ 03:24

Over the past couple of weeks I decided to take a look at Sony's public SDK for developing on the PlayStation® Vita. Getting to the point of being able to do a deployment was a bit painful, but after getting through those initial obstacles it's easy from there. A few things worth noting is that the SDK uses C# is the main programming language for making programs. It's running a custom version of Mono. Windows 8 isn't supported at this time, which causes some issues with getting the drivers installed that you will need for deployment. I've done a write up on what I had to do and have posted it over at CodeProject.com. You can find a detail account of what I had to do there. 

http://www.codeproject.com/Articles/535325/Hello-World-on-the-PlayStation-Vita-Deploying-code

Tags: ,

Nov 11 2012

Using XInput to access an Xbox 360 Controller in Managed Code

Category: Joel Ivory Johnson @ 11:30

download code

Introduction

A few years ago I wrote on using XNA to access the Xbox 360 controller from a Windows Form application. I had received a question about accessing the controller in an environment in which the XNA assemblies wouldn't be appropriate. So I wrote this code as an example of accessing the controller without the XNA assemblies. This is still a managed program. But it makes use of P/Invoke to use the functionality provided in the DirectX library.

Prerequisites

I wrote this code using Visual Studio 2012. It makes use of the XInput dll which is already part of Windows. So no additional installations are needed to use the code.

What is XInput

DirectX is composed of many libraries. There's Direct3D for for rendering 3D graphics, DirectSound for playing sound, and so on. DirectInput contains functionality for accessing various input devices (joysticks, keyboards, and more). But the Xbox 360 controller is not accessed through that library. It is accessed through a different library named XInput. This library is dedicated to the the Xbox 360 controller. Let's take a look at what is in the C language header file to see what functionality it provides. On my computer I can find the header in C:\Program Files (x86)\Windows Kits\8.0\Include\um\Xinput.h.

The header starts with defining the name of the DLL in which we will find the functionality.

#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
#define XINPUT_DLL_A  "xinput1_4.dll"
#define XINPUT_DLL_W L"xinput1_4.dll"
#else 
#define XINPUT_DLL_A  "xinput9_1_0.dll"
#define XINPUT_DLL_W L"xinput9_1_0.dll"
#endif

When a program is being compiled for an OS version before Windows 8 the functionality in the xinput1_4.dll. For programs compiled for Widnows 8 the functionality from xinput9_1_0.dll will be used. If you wanted to target both platforms you could make use of the older DLL (xinput9_1_0.dll). It will work on Windows 8 too. But the newer DLL (xinput1_4.dll) contains functionality for accessing the battery .

//
// Structures used by XInput APIs
//
typedef struct _XINPUT_GAMEPAD
{
    WORD                                wButtons;
    BYTE                                bLeftTrigger;
    BYTE                                bRightTrigger;
    SHORT                               sThumbLX;
    SHORT                               sThumbLY;
    SHORT                               sThumbRX;
    SHORT                               sThumbRY;
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;

typedef struct _XINPUT_STATE
{
    DWORD                               dwPacketNumber;
    XINPUT_GAMEPAD                      Gamepad;
} XINPUT_STATE, *PXINPUT_STATE;

typedef struct _XINPUT_VIBRATION
{
    WORD                                wLeftMotorSpeed;
    WORD                                wRightMotorSpeed;
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;

typedef struct _XINPUT_CAPABILITIES
{
    BYTE                                Type;
    BYTE                                SubType;
    WORD                                Flags;
    XINPUT_GAMEPAD                      Gamepad;
    XINPUT_VIBRATION                    Vibration;
} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;

There's also a section that contains the newer structures for functionality that became available with Windows 8.

#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8)

typedef struct _XINPUT_BATTERY_INFORMATION
{
    BYTE BatteryType;
    BYTE BatteryLevel;
} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;

typedef struct _XINPUT_KEYSTROKE
{
    WORD    VirtualKey;
    WCHAR   Unicode;
    WORD    Flags;
    BYTE    UserIndex;
    BYTE    HidCode;
} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE;

#endif //(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
    

Let's take a look at the structures redefined for .Net and C#.

struct XInputGamePad

The gamepad has two types of data to expose; information from the analog inputs and that from the digital inputs. The digital inputs include the A,B,X,Y, LB, and RB buttons.  It also includes the Start, Back, the four directions on the D-pad, and the buttonsunder the thumb sticks. The analog inputs include the two triggers and the two thumb sticks.  For the analog inputs there is a field for each input. The left and right triggers both an integer value between 0 and 255 in a byte. The thumb sticks return their X and Y values as 16-bit integers between the range of -32,768 and 32,767. The digital inputs are all returned in a single dield named wButtons.

[StructLayout(LayoutKind.Explicit)]
public struct  XInputGamepad
{
    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(0)]
    public short wButtons;

    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(2)]
    public byte bLeftTrigger;

    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(3)]
    public byte bRightTrigger;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(4)]
    public short sThumbLX;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(6)]
    public short sThumbLY;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(8)]
    public short sThumbRX;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(10)]
    public short sThumbRY;


    public bool IsButtonPressed(int buttonFlags)
    {
        return (wButtons & buttonFlags) == buttonFlags;
    }

    public bool IsButtonPresent(int buttonFlags)
    {
        return (wButtons & buttonFlags) == buttonFlags;
    }



    public void Copy(XInputGamepad source)
    {
        sThumbLX = source.sThumbLX;
        sThumbLY = source.sThumbLY;
        sThumbRX = source.sThumbRX;
        sThumbRY = source.sThumbRY;
        bLeftTrigger = source.bLeftTrigger;
        bRightTrigger = source.bRightTrigger;
        wButtons = source.wButtons;
    }

    public override bool Equals(object obj)
    {
        if (!(obj is XInputGamepad))
            return false;
        XInputGamepad source = (XInputGamepad)obj;
        return ((sThumbLX == source.sThumbLX) 
        && (sThumbLY == source.sThumbLY)
        && (sThumbRX == source.sThumbRX)
        && (sThumbRY == source.sThumbRY)
        && (bLeftTrigger == source.bLeftTrigger)
        && (bRightTrigger == source.bRightTrigger)
        && (wButtons == source.wButtons)); 
    }
}

The method IsButtonPressed accepts a constant that identifies the button of interest and will look in the wButtons member to see if the button is pressed and return true or false accordingly. I've added a few methods to make the the structure easier to use. The methods IsButtonPressed and IsButtonPresent have the exact same implementation. The same structure is used for querying the state of the controller and the capabilities of the controller.  I've added the two methods as a notational difference.

XInputVibration

The XInputVibration structure contains two unsigned integers between 0 and 65,535. The higher the value placed in the structure the faster the associated motor will be when it is turned on.

    [StructLayout(LayoutKind.Sequential)]
public struct  XInputVibration
{
    [MarshalAs(UnmanagedType.I2)]
    public ushort LeftMotorSpeed;

    [MarshalAs(UnmanagedType.I2)]
    public ushort RightMotorSpeed;
}

XInputState

The XInputState structure is an extension of the XInputGamepad structure with an additional field, PacketNumber. When the state of the controller is queried several times this value will continue to be the same if the the state of the controller is the same from the last time it was queried. If the state of the controller has changed then this value will be different.

[StructLayout(LayoutKind.Explicit)]
public struct  XInputState
{
        [FieldOffset(0)]
    public int PacketNumber;

        [FieldOffset(4)]
    public XInputGamepad Gamepad;

        public void Copy(XInputState source)
        {
            PacketNumber = source.PacketNumber;
            Gamepad.Copy(source.Gamepad);
        }

        public override bool Equals(object obj)
        {
            if ((obj == null) || (!(obj is XInputState)))
                return false;
            XInputState source = (XInputState)obj;

            return ((PacketNumber == source.PacketNumber)
                && (Gamepad.Equals(source.Gamepad)));
        }
}

XInputCapabilities

The XInputCapabilities structure returns the capabilities of the controller. Not all Xbox controlls have all of the available buttons on them, such as the dance pads which generally only contains.  Ironically the the Type field will always be populated with the same value (this may change in the future) and can be ignored for now. The field of interest is the SubType field. You can tell whether the controller is a gamepad, arcade stick, steeringwheel, or other type of controller. You can see a list of the controller types in the subtypes documentation page.  I've added the enumeration ControllerSubtypes to the XInputConstants.cs file which contains the possible values for this field. Other capabilities of the controller are indicated in the Flags member. This includes whether or not the controller is wireless, supports voice, has navigation buttons (start, back, dpad), supports force feedback, and whether it has a plugin module like the chat pad.  The possible values can be viewed in the enumeration CapabilityFlags in XInputConstants.cs.

The The next field is a XinputGamepad. For each one of the possible inputs there will be a non-zero value if the controller supports that input. After the XInputGamepad structure is a XInputVibration structure. Like the XInputGamepad if the left and right motors are supported there will be a non-zero value in the fields of this structure.

[StructLayout(LayoutKind.Explicit)]
public struct  XInputCapabilities
{
    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(0)]
    byte Type;

    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(1)]
    public byte SubType;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(2)]
    public short Flags;

        
    [FieldOffset(4)]
    public XInputGamepad Gamepad;

    [FieldOffset(16)]
    public XInputVibration Vibration;
}

XInputBatteryInformation

For controllers that use batteries this structure will indicate what type of battery that the control is using and indicated the battery level. The supported battery types are NiMH, alkaline, unknown, disconnected, and wired (for devices that don't actually use batteries). For the battery level only 4 values are supported to indicated empty, low, medium, and full. The values for both of these fields are also defined in the enumerations BatteryType and BatteryLevel in the XInputConstants.cs file.

[StructLayout(LayoutKind.Explicit)]
public struct  XInputBatteryInformation
{
    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(0)]
    public byte BatteryType;

    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(1)]
    public byte BatteryLevel;
}

XInput Functions

There are four functions that I use from the XInput library for interacting with the controller, XInputGetState, XInputSetState, XInputGetCapabilities and XInputGetBatteryInformation. All of these functions take as their parameters the index of the controller that is being manipulated and a reference to the structure into which information will be stored or retrieved. The two functions XInputGetBatteryInformation and XInputGetCapabilities take an additional parameter. For XInputGetBatteryInformation takes a parameter to the device type to be probed. If a user is using a wireless headset it could have it's own battery level separate from the level of the controller. The enumeration BatteryDeviceType contains values for BATTERY_DEVTYPE_GAMEPAD and BATTERY_DEVTYPE_HEADSET for this purpose. XInputGetCapabilities only accepts a single value of INPUT_FLAG_GAMEPAD for its additional value. This parameter could accept different values in the future as more capabilities are exposed.

        [DllImport("xinput1_4.dll")]
        public static extern int XInputGetState
        (
            int dwUserIndex,  // [in] Index of the gamer associated with the device
            ref XInputState pState        // [out] Receives the current state
        );

        [DllImport("xinput1_4.dll")]
        public static extern int XInputSetState
        (
            int dwUserIndex,  // [in] Index of the gamer associated with the device
            ref XInputVibration pVibration    // [in, out] The vibration information to send to the controller
        );

        [DllImport("xinput1_4.dll")]
        public static extern int XInputGetCapabilities
        (
            int dwUserIndex,   // [in] Index of the gamer associated with the device
            int dwFlags,       // [in] Input flags that identify the device type
            ref XInputCapabilities pCapabilities  // [out] Receives the capabilities
        );


        [DllImport("xinput1_4.dll")]
        public static extern int XInputGetBatteryInformation
        (
              int dwUserIndex,        // Index of the gamer associated with the device
              byte devType,            // Which device on this user index
            ref XInputBatteryInformation pBatteryInformation // Contains the level and types of batteries
        );

XboxController Class

Now that I've talked about all of the structures and functions available in XInput the one other class to present is one that I've made to manage the use of these other classes. I've wrapped the calls to the functionality in a class named XboxController class. The constructor for this class is private. There can only be up to 4 Xbox controllers on a system. So I've restricted the access to the constructor to prevent more than 4 instances from being created. To get an instance of a controller the static method XbocController.RetrieveController is available.

It's necessary to poll the controller to continually get updates about it's state. In an XNA or DirectX program this would be part of your game loop and so you don't really need to think about it. If you use the class in an environment without such a loop there are two options for getting updates to the controller. You could either call UpdateState manually or you could call the static method XboxController.StartPolling. The static method will create a new thread that will update the controller's state on some frequency. By default I've set this to 25 times per second. If you want to change it to some other value assign the number of updates per second that you want to received to the static member UpdateFrequency. When you nolonger wish to receive updates remember to call the XboxController.StopPolling method to end the thread. In the example code that I've attached to this article I call the StopPolling method when the program is closed.

protected override void OnClosing(CancelEventArgs e)
{
    XboxController.StopPolling();
    base.OnClosing(e);
}

There's a single event exposed by the class named StateChanged that is called if something about the controller's state has changed from the last thethat it was called.The e vent arguments for this event contain the current and previous state of the controller.

For making the controller vibrate call the Vibrate method. You could call this method by passing two double values (between 0.0d and 1.0d) to indicate how fast the motor should be. Values higher than 1.0 are clamped down to 1.0. Optionally you can specify the amount of time that the motor should be on. If no timespan is specific the motor will remain on until there's another call to Vibrate specifying a speed of zero. The polling loop for the Xbox controller class also checks to see if it is time to turn off any motors (if a timespan had been specified.

#region Motor Functions
public void Vibrate(double leftMotor, double rightMotor)
{
    Vibrate(leftMotor, rightMotor, TimeSpan.MinValue);
}

public void Vibrate(double leftMotor, double rightMotor, TimeSpan length)
{
    leftMotor = Math.Max(0d, Math.Min(1d, leftMotor));
    rightMotor = Math.Max(0d, Math.Min(1d, rightMotor));

    XInputVibration vibration = new XInputVibration() { LeftMotorSpeed = (ushort)(65535d * leftMotor), RightMotorSpeed = (ushort)(65535d * rightMotor) };
    Vibrate(vibration, length);
}
        

public void Vibrate(XInputVibration strength)
{
    _stopMotorTimerActive = false;
    XInput.XInputSetState(_playerIndex, ref strength);
}

public void Vibrate(XInputVibration strength, TimeSpan length)
{
    XInput.XInputSetState(_playerIndex, ref strength);
    if (length != TimeSpan.MinValue)
    {
        _stopMotorTime = DateTime.Now.Add(length);
        _stopMotorTimerActive = true;
    }
}
#endregion

Most importantly the XBoxController has a property input so that you can read its state. For the digital inputs reading one of the methods indirectly results in a call to IsButtonPressed.

#region Digital Button States
public bool IsDPadUpPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_DPAD_UP); }
}

public bool IsDPadDownPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_DPAD_DOWN); }
}

public bool IsDPadLeftPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_DPAD_LEFT); }
}

public bool IsDPadRightPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_DPAD_RIGHT); }
}

public bool IsAPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_A); }
}

public bool IsBPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_B); }
}

public bool IsXPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_X); }
}

public bool IsYPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_Y); }
}


public bool IsBackPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_BACK); }
}


public bool IsStartPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_START); }
}


public bool IsLeftShoulderPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_LEFT_SHOULDER); }
}


public bool IsRightShoulderPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_RIGHT_SHOULDER); }
}

public bool IsLeftStickPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_LEFT_THUMB); }
}

public bool IsRightStickPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_RIGHT_THUMB); }
}
#endregion

For the analog inputs a numeric value is returned for the left or right triggers, or a pair of numeric values (for X and Y directions) are returned for the thumbsticks.

#region Analogue Input States
public int LeftTrigger
{
    get { return (int)gamepadStateCurrent.Gamepad.bLeftTrigger;  }
}

public int RightTrigger
{
    get  {  return (int)gamepadStateCurrent.Gamepad.bRightTrigger; }
}

public Point LeftThumbStick
{
    get
    {
        Point p = new Point()
        {
            X = gamepadStateCurrent.Gamepad.sThumbLX,
            Y = gamepadStateCurrent.Gamepad.sThumbLY
        };
        return p;
    }
}

public Point RightThumbStick
{
    get
    {
        Point p = new Point()
        {
            X = gamepadStateCurrent.Gamepad.sThumbRX,
            Y = gamepadStateCurrent.Gamepad.sThumbRY
        };
        return p;
    }
}

#endregion

Tags: ,

Sep 30 2012

Setting the Display for a WPF Application

Category: Joel Ivory Johnson @ 14:56

I'm working on a presenttion project for which I needed to set the display on which a set of WPF applications are running. There's a total of 6 WPF applications that will be running on the same machine at once. Each application is going to be running on a different display. I thought I would share the solution that I used to control which display that each instance of this application went to. 

The first thing I needed to do was to retrieve the information on how how many displays that the computer has and the coordinates of each display. The computer creates a single (logical) display and maps each display device to cover a range of coordinates on this logical display. So I needed to retrieve a list of the displays and the coordinates to which it is mapped. The class available for doing this is in in the System.Windows.Forms library. Since I wasn't making a Windows Forms application I didn't want to add a using directive that would include the entire library; if I did there would be some class names that exists both in this name space and a WPF name space that I was using that could cause some resolution issues. So I only included the single class from the namespace. 

using Screen=System.Windows.Forms.Screen

The Screen class contains a member named <code>AllScreens</code> that contains a collection of <code>Screen</code> objects that give the information on each screen. If you wanted to make a simple WPF program that displayed all of the screens and their positions it only takes a few lines of code. The following is the code for the code-behind and the XAML for such a program. 

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = Screen.AllScreens;
    }
}
<Window x:Class="ScreenTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox ItemsSource="{Binding}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Vertical">
                        
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="100" />
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="{Binding DeviceName}" />
                            <TextBlock Grid.Column="1" Text="{Binding WorkingArea.X}" />
                            <TextBlock Grid.Column="2" Text="{Binding WorkingArea.Y}" />
                            <TextBlock Grid.Column="3" Text="{Binding WorkingArea.Width}" />
                            <TextBlock Grid.Column="4" Text="{Binding WorkingArea.Height}" />
                        </Grid>
                    </StackPanel>
                    
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>
 

Screenshot of the interface running

 

For the programs that I'll be running I've set device name for the program's intended display in a configuration file. The typical display name for the first display is \\.\DISPLAY1. I've made a method that will take the indended display name, try to find it, and set the position and size of the window accordingly.

void SetTargetDisplay()
{
    var targetDeviceName = Settings.Default.DisplayDevice;
    if(!String.IsNullOrEmpty(targetDeviceName))
    {
        // see if the device name specified exists here. It's possible
        // this was configured  to  run on a different machine and the 
        // configured device might not exists
        var screen = (from s in Screen.AllScreens 
             where s.DeviceName.ToLower().Equals(targetDeviceName.ToLower()) 
             select s).FirstOrDefault();
        if (screen != null)
        {
            Left = screen.WorkingArea.Left;
            Top = screen.WorkingArea.Top;
            Width = screen.WorkingArea.Width;
            Height = screen.WorkingArea.Height;
        }
    }
}

If the display doesn't exists (which could happen because of a typographical error or the program having been configured for another machine) then the method will just ignore the request.

 

Tags:

Sep 14 2012

Sidereal Time Calculator

Category: MobileJoel Ivory Johnson @ 04:12
Download Code (1.15 MB)
   

Introduction

There are a number of applications available on various mobile devices that allow you to aim your device at the sky and identify various heavenly bodies. I find the ability of identifying a body based on a user's location and the device's orientation fascinating. I find it even more fascinating when I see physical hardware acting on this information; the telescope I have uses GPS (to get my location and the current time) and uses this information to automatically move the telescope to the orientation needed to see selected body.

I now have a pretty good understanding of how it works. A significant amount of the calculations involved are based on time and another part is based on coordinate conversion. With the right time conversions you'll have enough information to get the orientation of the stars. (Getting the orientation of the planets and moon requires a little more work, but the stars have no apparent motion with respect to the solar system). I only want to talk about time for now, as there's more than enough information on time to fill an article.

Table of Contents

Terms and Time Units

Time is usually described in terms of some cyclic process or event where the units of time are from counting the cycles/events. This could be from the vibration of a crystal, the passing of some celestial, or some other event. Historically the apparent motion of the sun and moon have been used as the periodic event around which our time system was based. We've all used the units of time that are derived from these events; hours, minutes, seconds, years, and months along with the terms AM, PM, AD, and BC, and degrees. Let's dissect the physical events behind these terms.

Roman Calendar

The Roman calendar is said to have been invented by Romulus (the founder of Rome) around 753 years BC. This calendar had 10 months with the vernal equinox being the first month. The calendar had 304 days plus an additional number of winter days that stretched from December to the following month that were not part of any month on the calendar.

Julian Calendar

The Julian calendar is a modified version of the Roman Calendar. It has 365 days divided into 12 months. Once every 4 years a leap day is added.  It sounds very much like the civil calendar that we use today with the exception we don't have leap days on years divisible by 400 but not a millennium. With enough time solar and seasons events would begin to creep to other parts of the calendar. This was corrected with the Gregorian calendar.

Gregorian Calendar, Astronomical Year, and Julian Dates

The Gregorian calendar (also called the Western Calendar or Civil Calendar) is the name of the calendar that most of the world knows, loves, and uses today. The namesake for the calendar is Pope Gregory XIII. The number of times the earth rotates during its orbit around the sun is 365 times plus some fractional units (approximately 0.2524).   The Julian calendar made an attempt to correct this by introducing a leap year every 4 years. This contribution slowed the rate at which the seasons migrated on the calendar but didn't stop it all together. Pope Gregory XIII's contribution to the calendar was to not have a leap year if the year was divisible by 400 and is a  millennial year. The last day of the Julian calendar was Thursday 4 October 1582. The day that came after this was the first day of the Gregorian calendar; Friday 15 October 1582. The date range of 5-14 October (inclusive) doesn't exist - something that needs to be remembered for time conversions that cross this boundary.

Julian Date

Another commonly used calendar is counting the number of days since noon of 1 January 4713 B.C. This is also called a Julian date. Noon of 1 January 4713 is Julian date 0. Midnight between 1 January 4713 and 2 January 4714 is Julian date 0.5. Note that the time of day is a part of the Julian date as a fractional unit. For more recent dates the number used to express the Julian date is over 2,400,000 million. To avoid dealing with unnecessarily large numbers there's also the Modified Julian Date (MJD) which counts the number of days since midnight 17 November 1858. Note that MJD starts at midnight while JD starts at noon. So the time units in these two date expressions will have a difference of 0.5 for the digits after the decimal point. You may also hear of a Julian Date Number, which is just the integer portion of the Julian Date.  Dates of this form are of special significance to astronomical calculations.

AD, BC, and Astronomical Year

One of the oddities about the system of tracking years is that there is no year zero. The first year of the calendar , based on the reckoned conception of Jesus Christ of the Christian religion, is 1 AD (AD = Anno Domino, Latin for "Year of the lord", also written as "CE" for Common Era). The year immediately proceeding this is 1 BC (BC = Before Christ. Sometimes written as BCE for Before Common Era). When doing astronomical calculations no one wants to deal with the lack of the zero. So there is also the concept of the Astronomical Year. Astronomical years for the most part align with our current system of tracking years. So 1984 AD is also the Astronomical Year 1984. The difference is apparent when you look at years in the BC range. 1 BC is the astronomical year 0. 2 BC is the astronomical year -1, and so on.

Solar Day

A solar day is the period over which the sun apparently moves on a path and returns to it's starting point. I say apparent because while we know this phenomenon is from the earths rotation. But the movement of the sun is still described in geocentric terms (sun rise, sun set, so on). The sun's path varies slightly from one day to another so it doesn't really return to it's starting point. So the meridian is used as the starting line. The meridian is the imaginary circle around the globe stretching from the north pole to the south pole. The  sun and other bodies reach their highest point in the sky at the meridian and then go from climbing to declining. This line is also used to divide a day in half. Once the sun goes past the meridian the time is labeled as post meridian (P.M.). When it passes this line on the opposite side of the globe we say that it is in it's before meridian. The Latin word for before is "ante", so it is referred to as A.M. (for Ante Meridian). When the sun is on the meridian it is at its highest point in the sky. This is called "solar noon." Solar noon doesn't necessarily occur at the same instance in which the local time is 12:00 PM. There are slight variations in the time at which the sun reaches this point that we tend to ignore with civil clocks.

The pathway that the sun travels around an observer us usually divided into 24 units . Note that if you divide the 360 degrees of a circle by 24 you get 15. These 24 equal units are called hours (in other words, one hour of rotation is 15 degrees). These 15 degrees may also be divided into 60 units (minutes). A minute of rotation is 15/60, or 0.25 of a degree. As you may have guessed the next level of division is to divide a minute into 60 equal parts (the second) which contains 0.26/60 of a degree. An inference that you can make from using hours, minutes, and seconds (HMS) are a rotational unit is that for every hour that passes you can approximate the rotational distance that a celestial body in the night sky will travel over a unit of time; in a 2 hour period an object will travel 60 degrees. I say approximate because if you measure the distance with a high precision you'll see that the sun and moon appear to move by a slightly different amount than 60 degrees over this time period. For casual observations this difference won't be noticeable.

Sidereal Day

If you use the sun as your reference for rotation distance it appears that the earth takes 24 hours to make one full rotation. This isn't quite correct though. The earth moves about 1 degree on its orbit around the sun each day. So the sun shouldn't be used for an accurate measurement of how far the earth has rotated. Any other star will do though. The other stars are far enough away such that their apparent position is the same regardless of where the earth is on its orbit.

Difference in sidereal and solar day.

Choose a star (other than our sun, any star will do). Every time the earth rotates that star will reach the meridian. if you used a wall clock to measure the amount of time it takes for a star to reach the meridian again you'll find it isn't quite 24 hours. It is 23 hours 56 minutes and 4 seconds. Days measured using this method are sidereal days. Because these days are a bit less than 24 hours the amount of solar days in a sidereal year is about 366.25 instead of 365.25. Since a sidereal day is shorter than a solar day on any given solar day there will exist a range of sidereal times that occur twice within the solar day.

Time zones

Our universal time system is based on the time at Greenwich. Greenwich is on the zero longitude. Observations of celestial events on it's meridian was once the foundation of our timing system. It's meridian is also called the prime meridian. As a matter of convenience we also have the concept of local time, which is derived by adding some number of minutes and hours to the time at Greenwich. The earth is divided into 40 regions that share local time. These areas, or time zones, usually have a time difference by some interval of hours from the time at Greenwich (GMT). there are some time zones that are also offset by some hour interval plus 30 minutes. The difference from the most positive offset to the most negative offset is 26 hours. On average the difference between time zones can be inferred by their longitude (recall that one hour is 15 degrees of rotation). However the time zone lines are not straight. Rather than divide small geographic areas into several time zones the time zone borders will coincide with the borders of that geographical region.

The Earth's Celestia Movements

The stars are perceivably in a fixed position. For some one that wants to be extremely technical the stars are moving at speeds that we would find to be incredibly fast relative to our position or relative to the galaxy in which they rotate. But they are so far away that their movement is imperceptible to us, allowing us to treat them as stationary bodies over short periods measured in hundreds of years. There are a few factors that impact the orientation of the stars with respect to an observer on the earth.

Of these movements the one that has the most immediate impact on an observer is the rotation of the earth. Its impacts are directly observable through the apparent path that the sun, moon, and other bodies travel through our sky. If you are looking at a body with a telescope the movement becomes more apparent unless you have a motorized telescope that automatically adjust; as you look at a body it will drift out of the view of your telescope within a minute or less. This is the movement with which I am most concerned.

The Earth advances about 1 degree per day as it travels around the sun. With each day that passes the part of the celestial sphere that becomes unobservable due to competing light with the sun will slightly shift. This will mean that some stars will not be visible during certain parts of the year. While their direction can still be determined with the exception of an eclipse you won't be able to observer these stars during the day. Also note that this impacts the time of sun rise, sun set, and the number of hours in a day in which sunlight is visible (there's less hours of daylight in the winter). For now I'm not particularly concerned with what hours a star will be visible during my general case scenarios. Since I only use my telescope when time and weather unexpectedly permit I don't do much fore planning. If you've got interest in this I would suggest first explore the definitions on the various definitions of twilight (ex: civil vs. nautical vs. astronomical).

The third movement occurs over the course of about 25,700 years. It causes a slight circular drift of the direction in which the earth's rotational axis is pointing.  It can be addressed through a time dependent coordinate space adjustment. But I don't want to talk about coordinate conversions in this post. Just in case you are curious, the Earth's shift of the direction of it's rotational axis is about 1 degree every 71 years, so we can ignore this movement for now and it won't have a significant impact on our results.

Local Sidereal Time

Because of the continually varying orientation of the earth with respect to the sun we don't want to use a solar day for calculations of where stars are located with respect to the earth. The sidereal time is what we want. To get the sidereal time we need to know the Julian date. We'll get the Julian date from the civil (Gregorian) date. I've made a set of extensions for getting these dates. In calculating the Gregorian date you will need to be able to calculate how far we are into a day in decimal format. 12:00 Noon would be 0.5 into a day, 18:00 is 0.75 into a day, and so on. These can be easily calculated from a date or a time.

 static double ToFractionalDay(this TimeSpan sourceTime)
{
    return sourceTime.TotalHours / 24d;
}

 static double ToFractionalDay(this DateTime sourceDate)
 {
     return sourceDate.TimeOfDay.ToFractionalDay();
 }

These are written as extension methods because I find the calling syntax to be cleaner.  Now that we know how far we are into a day we can use that information to calculate the Julian date.

public static double ToJulianDate(this DateTime  sourceDate)
{
    double y, m, c;
    if (sourceDate.Month <= 2)
    {
        y = sourceDate.Year - 1;
        m = sourceDate.Month + 2;
    }
    else
    {
        y = sourceDate.Year;
        m = sourceDate.Month;
    }

    double leapDayCount  = (sourceDate > GregorianReformDate) ? (2 - Math.Floor(y / 100) + Math.Floor(y/400) ) : 0;
    if (sourceDate.Year < 0)
        c = (int)(365.25 * (double)sourceDate.Year - 0.75);
    else
        c = (int)(365.25 * (double)sourceDate.Year);
    double d = Math.Floor(30.6001 * (m + 1));
    var retVal = leapDayCount +c+ d + sourceDate.Day + 1720994.5;
    return retVal + sourceDate.ToFractionalDay();;
}

There's something I've not mentioned. All of these calculations are centric to the 0 longitude and are based on the GMT time zone without daylight savings. If you want to adjust the results to figure out the orientation of your time zone with respect to the rest of the observable universe you'll need to make an adjustment for your longitude. If your longitude is to the west of GMT express it with a negative number, otherwise use a positive number. Divide this number by 15 and add it to the sidereal time.  I live 84 degrees west of the 0 longitude. So to get the local sidereal time I do the following.

localSiderealTimeClock.CurrentTime = DateTime.Now.ToUniversalTime().ToSiderealTime().Add(TimeSpan.FromHours(-84d/15d));

The local sidereal time describes your rotational displacement from the direction of the vernal equinox (♈). While there's no up in space the direction formed by drawing a line from the sun to the earth while it is in the vernal equinox is the foundation of a couple of celestial coordinate systems (Ecliptic, which is based on the earth's orbit around the sun and equitorial which is based on the earth's rotation).

Correcting Variance's in the User's Clock

User's both intentionally and unintentionally may have their clocks set to an incorrect time. One way of avoiding problems from this is to make use of NTP (Network Time Protocol). I've written on obtaining NTP time before. You can read about it here.  While it is possible to continually poll an NTP source for the time I only grab it once every few minutes. When I get the NTP time the difference between the user's close and the NTP time source is saved and added to the value that comes from the user's clock. The expectation is that between refreshes for the NTP time the user's clock will reliably count seconds without any significant drift (if it doesn't, then the user needs a new device!).

NtpClient _ntpClient;
TimeSpan _ntpOffset;
DateTime _lastNtpRefresh = DateTime.MinValue;
TimeSpan _ntpRefreshPeriod = TimeSpan.FromMinutes(1);

public MainViewModel()
{
    _ntpClient = new NtpClient();
    _ntpClient.TimeReceived += new EventHandler<NtpClient.TimeReceivedEventArgs>(_ntpClient_TimeReceived);
    //Default the difference to zero and provisionally assume the user's
    //clock is correct until we receive information of otherwise
    _ntpOffset = TimeSpan.Zero;
}

void _ntpClient_TimeReceived(object sender, NtpClient.TimeReceivedEventArgs e)
{
    _lastNtpRefresh = DateTime.Now;
    DateTime NtpTime = e.CurrentTime;
    // NTP time is always in universal time, so we need to adjust the system clock 
    // to universal before getting the time offset. 
    _ntpOffset = NtpTime.Subtract(DateTime.Now.ToUniversalTime());
}

//Use thie method to get time adjusted for NTP offset.
DateTime GetDate()
{  
     return DateTime.Now.Add(_ntpOffset);
}

Displaying the Time

If you've looked at clocks that show the time in more than one time zone chances are the numbers shown for minutes and seconds were the same for most of the time zones. This isn't the case when looking at both civil time and sidereal time. The seconds will be out of sync. Because of personal preference (I simply find this displeasing) I'm updating the seconds simultaneously. I've made two controls for displaying the time; an analog clock and a digital clock. Both can display the time in 12 hour or 24 hour format.

 

Digital display of sidereal clock.

Displaying the 24 hour time with an analog clock may be new to many. I took a look at several 24-hour analog clocks in images online. Some started with midnight at the top of the clock and others with midnight at the bottom. I decided on having the midnight (0) hour at the bottom. This places noon at the top of the clock. Displaying 24-hour time in sidereal format is something that I'm still playing with though. While I have a circular gauge-like clock in place I'm going to change this from a user control to a templated control and expose new options on how it's to be rendered. (hints of the forthcoming changes are visible in the source code).

 
Display of analog class
 
Options screen

Help Files

In experimenting with something else I've included a Help HTML file for the application. The help file is stored in the application as content but unpackaged the first time the application is run. To prevent the unnecessary unpacking of files every time the application run it checks to see if a file already exists before unpacking it.

public class ContentUnpacker
{
   
    static string[] ContentFileList = { "About.html", "Sidereal.png", "appTimes.png", "settings.png" }; 
    public static void UnpackAllFiles()
    {
        IsolatedStorageFile sourceArchive = IsolatedStorageFile.GetUserStoreForApplication();
        if (!sourceArchive.DirectoryExists("Content"))
            sourceArchive.CreateDirectory("Content");


        foreach (string s in ContentFileList)
        {
            string targetName = String.Format("Content/{0}", s);
            string sourceName = String.Format("Content/{0}", s);
            if(!sourceArchive.FileExists(targetName))
            {
                var outStream = sourceArchive.CreateFile(targetName);
                var contentStream = Application.GetResourceStream(new Uri(sourceName, UriKind.Relative));
                using (var br = new BinaryReader(contentStream.Stream))
                {
                    var length = (int)br.BaseStream.Length;
                    outStream.Write(br.ReadBytes(length), 0, length);
                }
            }   
        }
    }
}

The about page contains only a web browser element that is given the URL to the help files. The entirity of the code that's behind the about page is below.

public partial class AboutPage : PhoneApplicationPage
{
    public AboutPage()
    {
        InitializeComponent();
    }

    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
    {
        aboutBrowser.Navigate(new Uri("Content/About.html", UriKind.Relative));
    }
}

Where to from Here

There's a number of applications, some related to astronomy and others not that I have in mind for which this functionality will be useful. One example of something not realted to astronomy was an augmented reality application I had in mind for which I wanted the application to shade the models projected on the screen according to the location of the sun. One of the astronomy related applications is that I have access to a room with projectors and screens on all 4 walls. Just for the fun of it I wanted to to get the computers that control the projectors on all 4 walls communicating with each other and displaying a 360 view of the solar system. Getting the sidereal time is a stepping stone for some of these other applications but not the end goal itself. I plan to write on how these other ideas progress as each one of them gets implemented.

Figures and Illustrations

Revision History

  • 2012-09-14 - Initial publication

 

 

 

 

Tags: , ,

Jun 29 2012

Windows Phone 8 Marketplace for 180 Countries

Category: MobileJoel Ivory Johnson @ 07:23

We've come a long way since Microsoft initially launched it's mobile Marketplace. The original Windows Marketplace for Mobile was available to about 30 nations. If you didn't live in one of those nations and you wanted an application that was only distributed through the Marketplace then there was no way to get it. On Windows Phone 7 (unlike Windows Mobile) the Marketplace was the *only* way to load programs, so the implications were even different. At the time of this writing Microsoft has the Marketplace available in 60 countries. But they have  recently announced that the Marketplace for Windows Phone 8 will be available in 180 countries and will make in-app purchasing available (increasing your opportunity for making money). 

Source: Windows Phone Team Blog

Tags: , ,

Apr 22 2012

RestSharp and Windows Metro

Category: Joel Ivory Johnson @ 01:26

I've got RestSharp (partially) working on Windows Metro. I've been able to make a simple Metro application and make a few rest calls. Though right now some encryption and signature related functionality isn't yet working. 

I can't seem to run the unit test in Visual Studio 11 and may try to resolve that later this week. But if you want to take a look at my changes thus far you can find them on github.com

https://github.com/j2inet/RestSharp

 

Tags: , ,

Apr 17 2012

Compiling Same Code on Windows Phone 7 and Windows 8 Metro

Category: Desktop and Server | MobileJoel Ivory Johnson @ 12:27
Download Code (1.14 MB)

I was thinking about how to write code that will work on both Windows Phone 7 and Windows 8 (Metro). In theory some of the techniques that could be used are well known. But I wanted to try them out. So I decided to try some things out in a piece of throw away code. This gives me some liberty to experiement without worrying about the long term consequences of having not chosen the "best" way. For my throw away application I decided to make an application that would grab some one's Facebook friend list and display it on the screen. So this code will necessarily need to authenticate the user against Facebook. If you've not worked with the Facebook APIs before don't worry about it too much. You should still be able to follow along since this isn't digging deeply into what's available.

I've managed to use some of the techniques to make a Windows Metro version of RestSharp. I'll talk about that in another post.

Register your Application

Before you begin doing any coding you'll want to register your new Facebook application in the Facebook developer portal. This also means that you need to have a facebook account. Because I didn't want to bother my associates with test items in my feed I also created a secondaty facebook account for testing. The portal is available at developer.facebook.com. Clicking on menu item "Apps" at the top of the screen will take you to a page that shows all of your registered applications (if any) and will let you register more. If this is your first time using the portal you'll have no applications. I'll walk you through registering an application. I'll only draw your attention to options as necessary. Options that I don't mention can be left in their default state (which will most likely be blank).

Click on the "Create New App" button. You'll get prompted with a dialog in which you will need to enter the name of the application that you are creating. The dialog will automatically validate the name that you've entered once you've stopped typing and will let you know if a chane needs to be made. Once you have a name that the dialog considers valid click on the "Continue" button.

The next dialog is a Captcha. I really dislike Captchas. While I understand that these dialogs exists to make sure that a bot is not registering the new application the problem that I have with them is that more times than not I'm going to get the entry wrong a few times (ex: is that third character a lowercase 'L', upper case 'L', or an uppercase 'I'?).

Once you pass the Captcha you'll get an opportunity to specify the other details for your application and a chance to change the application's icon and category. It may not be obvious which option to select for "Select how your app integrates with Facebook." None of the available options has a description that you would automatically assocate with a Windows Phone or Metro application. Select "Website". During development it doesn't matter if the website that you've specified exists or not. But you will need to enter an address to a page that would  in theory process the login information. Once you've entered this information select "Save Changes." There are three pieces of information that are on this page that you'll be copying into your application later on: App ID, App Secret, and the Site URL. Keep this page open so that you can copy the information when I refer to it later.

 

 

Now to make your mobile application. At the time of this writing you'll need to use Visual 2010 for Windows Phone applications and Visual Studio 11 for Windows Metro applications. Most of what will be done will be similar enough such that I can talk about the procedure to be followind in parallel and note the occasional differences as they arise.

Creating the New Application Projects

I created both a Silverlight Application for Windows Phone and a Windows 8 Metro project. There are going to be significant blocks of code that will be identical between these two projects. When this occurs I'll only create one version of the file but will have it referenced in both projects. Linked files can easily be recognized by the arrow that shows in the lower-left corner of their icon. If you've never linked files before you can find more information on it here.

How linked files appear in Visual Studio.

Conditionally Compiled Code

There still may be sections in thee files that are specific to Windows Phone or Windows 8. These sections will be conditionally commented out depending on the platform on which the code is being compiled. For code that is specific to Windows 8 Metro applications the code is wrapped in #if NETFX_CORE/#endif blocks. For Windows 7 code I've wrapped the code in #if SILVERLIGHT/#endif blocks. I could have also used #if WINDIWS_PHONE/#endif blocks

If there is a large block of code that is specific to one platform and not the other instead of using the conditional compilation directives one could choose to just include the file containing the code in one file and not in the other. You'll see this done with most of the UI code (the XAML, while similar, is not shared between the two projects).

Creating the Authentication Page

Before I can call any method in Facebook I need to authenticate the user. Facebook uses a form of open authentication. So we will need to use a web browser in the application. Add a new page to your project caled "AuthenticationPage.xaml." The only element that is necessary in this page will be the web browser.  Many of the differences that you will encounter between Metro and Windows Phone 7 are in UI related code. There's a slight difference in the element that needs to be used for representing a browser element.

 <WebView 
     x:Name="AuthenticationWindow" 
     HorizontalAlignment="Stretch" 
     VerticalAlignment="Stretch"
     LoadCompleted="AuthenticationWindow_LoadCompleted" 
/>
 
<phone:WebBrowser  
   Name="AuthenticationWindow" 
   HorizontalAlignment="Stretch"
   VerticalAlignment="Stretch" 
   Navigated="AuthenticationWindow_Navigated" 
/>
Browser element for Windows Metro
 
Browser element for Windows Phone 7

The Application Constants

There are a few elements of data to which we will need. They are all in the entries for the app that you registered with Facebook. I'll need to use these in more than one place. The logic needed for authentication is simple and I left it in the UI code.  I separated the logic that will be shared in the Metro and WP7 versions of this application into a partial class definition. That

static class ApplicationConstants
{
	const string REDIRECT_URL = "https://mysite.com/SomePostAuthenticationPage.html";
	const string APP_ID = "_YOUR_APP_ID_";
	const string APP_SECRET = "_YOUR_APP_SECRET_";
	const string PERMISSIONS = "read_friendlists";
}

You'll need to substitute the values for your own application in these constants (except for the PERMISSIONS constant).

Creating the Authentication Page

An extremely high level overview of what occurs in the code-behind for the authentication page is that it will load the Facebook Open Authentication page and then monitor the path to which the user navigates. If the user has authenticated the browser will be directed to the site that had been registered for the application earlier. When this occurs there will be an authentication code appended to the URL. That code will be parsed out and exchanged for a token. There's not much the UI is really doing. So the codebehind looks simple. 

public partial class AuthenticationPage : PhoneApplicationPage
{
   public AuthenticationPage()
   {
      InitializeComponent();
      ViewModel = (App.Current as J2i.Net.FacebookAuthenticationTest.App).ViewModel;
      ViewModel.AuthenticationAttempted = true;
   }

   private void AuthenticationWindow_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
   {
   }

   private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
   {  
      PrepareForAuthentication();
   }

   private void AuthenticationWindow_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
   {
   }

   private void AuthenticationWindow_Navigating(object sender, NavigatingEventArgs e)
   {
      ProcessWebPageLoad(e.Uri.ToString());
   }
}
Code-behind for the Windows Phone version of the application

Handling Code Differences with Partial Classes

Where there is a slight difference in the code behind for the two pages the rest of the logic is the same. Instead of duplicating it I put the common logic in a partial class definition. The partial class has the same name as the class for the page. So at compile time the code from the code-behind and the partial class will be compiled into a single class. The common code is in AuthenticationPage.xaml.shared.cs.  The first method that the code-behind references from the shared file is PrepareForAuthentication(). This method will build the authentication URL which contains parameters to allow the application to identify itself, what permissions are needed, and a random string that should be passed for security reasone. If you want to see more information on these parameters they can be found in the Facebook authentication documentation.

void PrepareForAuthentication()
{
    _unique = Guid.NewGuid().ToString();

    string targetUrl = String.Format("https://www.facebook.com/dialog/oauth?" +
                                        "client_id={0}" +
                                        "&redirect_uri={1}" +
                                        "&scope={2}" +
                                        "&state={3}",
                                        // for touch/phone friendly version of the authentication page
                                        //"&display=touch",
                                        Uri.EscapeUriString(ApplicationConstants.APP_ID),
                                        Uri.EscapeUriString(ApplicationConstants.REDIRECT_URL),
                                        Uri.EscapeUriString(ApplicationConstants.PERMISSIONS),
                                        Uri.EscapeUriString(_unique));
    AuthenticationWindow.Navigate(new Uri(targetUrl));
}

The ProcessWebPage() method looks at the URL to which the browser is navigating to see whether or not it is our redirect URL. If it's not then nothing happens. If it is then the query parameters are extracted. Theparameters we are most interested in are code and state since these will indicate a successful authentication attempt. The code will be needed to request an access token for making Facebook API calls.

void ProcessWebPageLoad(string targetUriString)
{
   if (targetUriString.IndexOf(ApplicationConstants.REDIRECT_URL) == 0)
   {

      string _code = GetQueryParam(targetUriString, "code");
      string _state = GetQueryParam(targetUriString, "state");
      string _error = GetQueryParam(targetUriString, "error");
      string _errorReason = GetQueryParam(targetUriString, "error_description");
      string _errorDescription = GetQueryParam(targetUriString, "error_reason");

      if (
         (!String.IsNullOrEmpty(_code)) &&
         (!String.IsNullOrEmpty(_state)) &&
         (_unique.Equals(_state))
      )
      {
         ExchangeCodeForAccessToken(_code);
      }
   }
}

Requessting the access token is another web call, but it's not one for which we need the browser. It doesn't return anything user friendly so we can make the call without using the browser. Getting the access token is just a matter of building a URL and grabbing the token from the results.

void ExchangeCodeForAccessToken(string code)
{
    //Building the Request URL
    string targetUrl = String.Format("https://graph.facebook.com/oauth/access_token?" +
                                        "client_id={0}" +
                                        "&redirect_uri={1}" +
                                        "&client_secret={2}" +
                                        "&code={3}",
                                        Uri.EscapeUriString(ApplicationConstants.APP_ID),
                                        Uri.EscapeUriString(ApplicationConstants.REDIRECT_URL),
                                        Uri.EscapeUriString(ApplicationConstants.APP_SECRET),
                                        Uri.EscapeUriString(code));
    var webRequest = HttpWebRequest.CreateHttp(targetUrl);

    //Request the URL
    webRequest.BeginGetResponse((o) =>
    {
        //Stuff the response into a string
        var response = webRequest.EndGetResponse(o);
        var rs = response.GetResponseStream();
        StreamReader sr = new StreamReader(rs);
        var responseString = sr.ReadToEnd();

        //Get the access token and its expiration date
        string accessToken = GetQueryParam(responseString,"access_token");
        DateTime expirationDate = DateTime.MinValue;
        string expiresString = GetQueryParam(responseString, "expires");

        if (!String.IsNullOrEmpty(expiresString))
        {
            int expireTime;
            if (int.TryParse(expiresString, out expireTime))
            {
                expirationDate = DateTime.Now.AddSeconds(expireTime);
            }
        }

        //If we successfully got a token and expiration save them, start grabbing the
        //friend list, and then navigate to the previous page
        if (!String.IsNullOrEmpty(accessToken) && (expirationDate != DateTime.MinValue))
        {
            ViewModel.AccessInfo = new AccessInfo() { ExpirationDate = expirationDate, Token = accessToken };
            ViewModel.SaveAccessToken();
            ViewModel.UpdateFriendList();
            ReturnToPreviousPage();
        }
    }, null);
}

Navigation is a little different on Windows Phone 7 and Windows 8. So I added a ReturnToPreviousPage() method in both the code-behind for the Metro and Windows Phone 7 versions of the application. Each of which contains the appropriate version of the navigation code.

void ReturnToPreviousPage()
{
   ViewModel.DispatchInvoke(() =>
   {
      (Window.Current.Content as Frame).GoBack();

   }
   );
}
 
void ReturnToPreviousPage()
{
   ViewModel.DispatchInvoke(() =>
   {
       NavigationService.GoBack();
   }
   );
}
Windows 8 Metro Version
 
Windows Phone Version

Retreiving the Friend List

The code for retrieving the friend list looks identical on both platforms. Facebook may not return the entire friend list in one call. If there are more friends to be retrieved in the return structure from the call there will be an address in a member in the return structure named Next (nested in Paging) which contains the address to the next page of the results. I'm not parsing the results myself but am instead making use of JSON.Net by James Newton-King. The results are parsed and accumulated into a temporary list. Once I know that I have all the results they are moved to the bindable list that drives the list box on the UI.

public void UpdateFriendList(string targetUrl = null, List previousUserList = null)
{
    if (AccessInfo == null)
        return;
    if (previousUserList == null)
        previousUserList = new List();

    var request = System.Net.HttpWebRequest.CreateHttp(targetUrl ?? String.Format(FRIEND_LIST_REQUEST, AccessInfo.Token));
    request.BeginGetResponse((o) =>
        {
            var response = request.EndGetResponse(o);
            var responseStreamReader = new StreamReader(response.GetResponseStream());
            string friendListText = responseStreamReader.ReadToEnd();
            Newtonsoft.Json.JsonSerializer s = new JsonSerializer();
            Data.FriendListResponse v = Newtonsoft.Json.JsonConvert.DeserializeObject(friendListText);
            if ((v != null) && (v.Data != null))
            {
                foreach (var user in v.Data)
                {
                    previousUserList.Add(user);
                }
            }
            if ((v!=null) && (v.Paging != null) && (v.Paging.Next != null))
                UpdateFriendList(v.Paging.Next, previousUserList);
            else
            {
                previousUserList.Sort((a1, a2) => { return a1.Name.CompareTo(a2.Name); });
                DispatchInvoke(() =>
                    {
                        FriendList.Clear();
                        foreach (var u in previousUserList)
                            FriendList.Add(u);
                    }
                );
            }

        }, null);
}

Dispatching Differences

There is a rule in Windows Platforms that you cannot modify the UI from a seconday thread. On the XAML based platforms you can ensure calls that modify the UI are marshalled to the UI thread by making use of an object called the Dispatcher. The way that you use this object differs on Windows Phone 7 and Windows 8. I abstracted away the differences by making a method called DispatchInvoke(). It compiles different on each platform and will call the appropriate code on each platform.

public void DispatchInvoke(Action a)
{
#if SILVERLIGHT
    if (MainViewModel.Dispatcher == null)
        a();
    else
        Dispatcher.BeginInvoke(a);
#else
    if ((Dispatcher != null) && (!Dispatcher.HasThreadAccess))
    {
        Dispatcher.InvokeAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, (obj, invokedArgs) => { a(); }, this, null);
    }
    else
        a();
#endif
}

Saving Data

For saving simple data types I tend to use a simple component that I made for Windows Phone 7 (it can be found here). On Windows 8 all file IO is asynchronous. So the component had to be modified to work on Metro. I've shown the details of the changes on another page. Since the Windows Phone 7 version uses a blocking call and the Metro version is asynchronous the calls could not be made to look the same. But this difference was compatmentalized to a single method.

public void SaveAccessToken()
{
   if (this.AccessInfo != null)
   {
#if NETFX_CORE
      DataSaver<AccessInfo>.SaveMyDataAsync(this.AccessInfo, "_accessToken.xml");
#endif
#if SILVERLIGHT
     DataSaver<AccessInfo>.SaveMyData(AccessInfo, "_accessToken.xml");
#endif
   }
}

Most of the code for this project is in the MainViewModel class. The entirity of the code for it is below. It shouldn't contain anything that you don't recognize from above. The using directives at the top contain conditional compilation directives since the namespaces in which some of the classes exists differs on Windows Phone 7 and on Windows 8 Metro.

using System;
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using Newtonsoft.Json;
using J2i.Net.FacebookAuthenticationTest.Data;
using J2i.Net.FacebookAuthenticationTest.Utility;


#if SILVERLIGHT
using System.Windows.Threading;
#endif

#if NETFX_CORE
using System.Threading.Tasks;
using J2i.Net.FacebookAuthenticationTest.Data;
using Windows.UI.Xaml;

#endif

namespace J2i.Net.FacebookAuthenticationTest.ViewModel
{
    public class MainViewModel: INotifyPropertyChanged 
    {
        const string FRIEND_LIST_REQUEST = "https://graph.facebook.com/me/friends?access_token={0}";


        public MainViewModel()
        {
#if SILVERLIGHT
            var a = DataSaver<AccessInfo>.LoadMyData("_accessToken.xml");
            if(a !=null)
            {
                this.AccessInfo = a;
                this.UpdateFriendList();
            }
#endif

#if NETFX_CORE
            DataSaver<AccessInfo>.LoadDataAsync("_accessToken.xml", (info, exc)=>
            {
                if (info != null)
                {
                    this.AccessInfo = info;
                    this.UpdateFriendList();
                }
            });
#endif
        }

        ObservableCollection<FacebookUser> _friendList;
        public ObservableCollection<FacebookUser> FriendList
        {
            get { return (_friendList) ?? (_friendList = new ObservableCollection<FacebookUser>()); }
            set { _friendList = value; }
        }
 

        string _friendListText = String.Empty;
        public string FriendListText
        {
            get { return _friendListText; }
            set 
            {
                if (value != _friendListText)
                {
                    _friendListText = value;
                    RaisePropertyChanged("FriendListText");
                }
            }
        }


        public void SaveAccessToken()
        {
            if (this.AccessInfo != null)
            {
#if NETFX_CORE
                DataSaver<AccessInfo>.SaveMyDataAsync(this.AccessInfo, "_accessToken.xml");
#endif
#if SILVERLIGHT
               DataSaver<AccessInfo>.SaveMyData(AccessInfo, "_accessToken.xml");
#endif
            }
        }

        AccessInfo _accessInfo;
        public AccessInfo AccessInfo
        {
            get { return (_accessInfo) ?? (_accessInfo = new AccessInfo()); }
            set 
            {
                if (_accessInfo != value)
                {
                    _accessInfo = value;

                }
            }
        }

        bool _authenticationAttempted = false;
        public bool AuthenticationAttempted
        {
            get { return _authenticationAttempted || (!String.IsNullOrEmpty(AccessInfo.Token)); }
            set { _authenticationAttempted = value; }
        }

#if NETFX_CORE
        static Windows.UI.Core.CoreDispatcher _dispatcher;
        public static Windows.UI.Core.CoreDispatcher Dispatcher
        {
            get
            {
                if (_dispatcher != null)
                    return _dispatcher;
                if ((Window.Current==null)||(Window.Current.Content == null))
                    return null;
                return Window.Current.Content.Dispatcher; 
            }
            set { _dispatcher = value; }
        }
#endif

#if SILVERLIGHT
        static Dispatcher _dispatcher;
        public static Dispatcher Dispatcher
        {
            get
            {
                if (_dispatcher!=null)
                    return _dispatcher;
                var app = (App.Current as J2i.Net.FacebookAuthenticationTest.App);
                if (app.RootFrame == null)
                    return null;
                return (app.RootFrame.Dispatcher);
            }
            set
            {
                _dispatcher = value;
            }
        }    
#endif


        public void UpdateFriendList(string targetUrl = null, List<FacebookUser> previousUserList = null)
        {
            if (previousUserList == null)
                previousUserList = new List<FacebookUser>();

            var request = System.Net.HttpWebRequest.CreateHttp(targetUrl ?? String.Format(FRIEND_LIST_REQUEST, AccessInfo.Token));
            request.BeginGetResponse((o) =>
                {
                    var response = request.EndGetResponse(o);
                    var responseStreamReader = new StreamReader(response.GetResponseStream());
                    string friendListText = responseStreamReader.ReadToEnd();
                    Newtonsoft.Json.JsonSerializer s = new JsonSerializer();
                  Data.FriendListResponse v = Newtonsoft.Json.JsonConvert.DeserializeObject<Data.FriendListResponse>(friendListText);
                  if ((v != null) && (v.Data != null))
                  {
                      foreach (var user in v.Data)
                      {
                          previousUserList.Add(user);
                      }
                  }
                  if ((v!=null) && (v.Paging != null) && (v.Paging.Next != null))
                      UpdateFriendList(v.Paging.Next, previousUserList);
                  else
                  {
                      previousUserList.Sort((a1, a2) => { return a1.Name.CompareTo(a2.Name); });
                      DispatchInvoke(() =>
                          {
                              FriendList.Clear();
                              foreach (var u in previousUserList)
                                  FriendList.Add(u);
                          }
                      );
                  }

                }, null);
        }


        void DispatchInvoke(Action a)
        {
#if SILVERLIGHT
            if (MainViewModel.Dispatcher == null)
                a();
            else
                Dispatcher.BeginInvoke(a);
#else
            if ((Dispatcher != null) && (!Dispatcher.HasThreadAccess))
            {
                Dispatcher.InvokeAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, (obj, invokedArgs) => { a(); }, this, null);
            }
            else
                a();
#endif
        }
        protected void RaisePropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                DispatchInvoke(()=>
                    {
                        RaisePropertyChanged(propertyName);
                    });
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

Tags: , , ,

Apr 17 2012

Invoking through the Dispatcher on Windows Phone and Metro

Category: Desktop and Server | MobileJoel Ivory Johnson @ 09:26
Note: : Between the time that I wrote this and final release there were changes to the Windows Store Runtime. InvokeAsync nolonger exists. It has been replaced with RunAsync. Change noted below.

On the Windows Platforms there is a rule that you cannot modify UI elements from secondary threads. On Microsoft's XAML based platforms there is a member that exists on most UI objects called the Dispatcher that can be used to marshal a call to the proper thread.

On Windows Phone 7 and Windows 8 the way you go about calling this thread differs. I was recently working with some code that needed to compile for both platforms and wanted to minimize the amount of code that had to be wrapped in conditional compilation blocks. To do this I made a single method to handle my dispatching. The method itself contains conditional compilation blocks but because of this method I didn't need the blocks when I needed perform operations on the UI thread.

public void DispatchInvoke(Action a)
{
#if SILVERLIGHT
    if (Dispatcher == null)
        a();
    else
        Dispatcher.BeginInvoke(a);
#else
    if ((Dispatcher != null) && (!Dispatcher.HasThreadAccess))
    {
        Dispatcher.InvokeAsync( //RTM change
        Dispatcher.RunAsync(
                    Windows.UI.Core.CoreDispatcherPriority.Normal, 
                    (obj, invokedArgs) => { a(); }, 
                    this, 
                    null
         );
    }
    else
        a();
#endif
}

The code will compile for both Windows Phone 7 and Windows 8 Metro without any alterations. Using the code is the same regardless of which of the two platforms that you are using.

DispatchInvoke(()=>
  {
    //your operations go here
    TextBox1.Text="My Text";
  }
);

Tags: , , ,

Apr 15 2012

Data Serializer updated for Windows Metro

Category: Microsoft | MobileJoel Ivory Johnson @ 12:46

About a year ago I shared a simple utility class for saving serializable data on Windows Phone 7. I just updated the component for Windows 8 Metro. It still retains compatibility with Windows Phone 7 through the use of conditional compiler directives. On Windows Phone 7 I've changed the class so that it is static (so no need to instantiate it). 

For Metro the methos are asynchronous.  For saving an action can be passed that will be called once the save operation is complete. When loading data you'll want to pass an action that will received the loaded data and an exception parameter that will be populated if the data could not be loaded. 

 

As an example of how the code works (and the platform dependent differences in its usage) here is a method from a program I have that is using the code. The program compiles on both Windows Phone 7 and Windows Metro.

        public void LoadAccess()
        {
#if SILVERLIGHT
            AccessInfo = DataSaver<AccessInfo>.LoadMyData("_accessToken.xml");
#endif

#if NETFX_CORE
            DataSaver<AccessInfo>.LoadDataAsync("_accessToken.xml", (info, exc)=>
            {
                if (info != null)
                {
                    this.AccessInfo = info;
                }
            });
#endif
        }

        public void SaveAccessToken()
        {
            if (this.AccessInfo != null)
            {
#if NETFX_CORE
                DataSaver<AccessInfo>.SaveMyDataAsync(this.AccessInfo, "_accessToken.xml");
#endif
#if SILVERLIGHT
               DataSaver<AccessInfo>.SaveMyData(AccessInfo, "_accessToken.xml");
#endif
            }
        }

If you've never seen the #if/#endif directives before it is used to essentially conditionally comment out sections of code based on some condition. In this case the condition is certain compiler constants being defined. Some constants are automatically created for various project types. If you create a windows phone project the WINDOWS_PHONE and SILVERLIGHT constants are defined. For a Windows 8 Metro project the NETFX_CORE constant is defined. When you are viewing the code in the Visual Studio IDE it will gray out any code that is going to be ignored because of the conditional compilation statements. 

Below is the code for the serializer. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;

using System.IO;
#if SILVERLIGHT
using System.IO.IsolatedStorage;
#endif

#if NETFX_CORE
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
#endif

namespace J2i.Net.FacebookAuthenticationTest.Utility
{


    public class DataSaver<MyDataType>
    {

        static List<Type> _knownTypeList = new List<Type>();
        public static List KnownTypeList
        {
            get
            {
                return _knownTypeList;
            }
        }
#if SILVERLIGHT
        private static IsolatedStorageFile _isoFile;
        static IsolatedStorageFile IsoFile
        {
            get
            {
                if (_isoFile == null)
                    _isoFile = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();
                return _isoFile;
            }
        }

         public static void SaveMyData(MyDataType sourceData, String targetFileName)
        {
            try
            {
                using (var targetFile = IsoFile.CreateFile(targetFileName))
                {
                    var d = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                    d.WriteObject(targetFile, sourceData);
                }
            }
            catch (Exception )
            {
                IsoFile.DeleteFile(targetFileName);
            }
        }


        public static MyDataType LoadMyData(string sourceName)
        {
            MyDataType retVal = default(MyDataType);
            if (IsoFile.FileExists(sourceName))
                using (var sourceStream = IsoFile.OpenFile(sourceName, FileMode.Open))
                {
                    var d = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                    retVal = (MyDataType)d.ReadObject(sourceStream);
                }
            return retVal;
        }
#endif
        public DataSaver()
        {
        }
#if NETFX_CORE
        public static async void SaveMyDataAsync(
            MyDataType sourceData, 
            String targetFileName, 
            Action<MyDataType,String, Exception> OnSaved = null)
        {
            try
            {
                StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
                    targetFileName, CreationCollisionOption.ReplaceExisting
                    );
                IRandomAccessStream raStream = await file.OpenAsync(FileAccessMode.ReadWrite);
                IOutputStream outStream = raStream.GetOutputStreamAt(0);

                DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                serializer.WriteObject(outStream.AsStreamForWrite(), sourceData);
                await outStream.FlushAsync();
                if(OnSaved!=null)
                    OnSaved(sourceData, targetFileName, null);
            }
            catch (Exception exc)
            {
                if (OnSaved != null)
                {
                    OnSaved(sourceData, targetFileName, exc);
                }
            }
        }

        public static async void LoadDataAsync(string fileName, Action<MyDataType, Exception> loadAction)
        {
            if (loadAction == null)
                return;
            try
            {
                StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
                if (file == null) return;
                IInputStream inStream = await file.OpenSequentialReadAsync();

                // Deserialize the Session State. 
                DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                MyDataType data = (MyDataType)serializer.ReadObject(inStream.AsStreamForRead());
                loadAction(data, null);
            }
            catch (Exception e)
            {
                loadAction(default(MyDataType), e);
            }
        }
#endif

    }
}

Tags: ,

Apr 3 2012

Getting Assembly Version Number in WinRT

Category: Desktop and Server | MobileJoel Ivory Johnson @ 09:19

It seems that every time one makes a shift from one .Net platform to another the method you use to reflect the version number for an assembly changes. I needed to get this information for a WinRT program earlier and was able to do so with a regular expression and the slightly different reflection methods in WinRT. The code follows:

 

var asmName = this.GetType().AssemblyQualifiedName;
var versionExpression = new System.Text.RegularExpressions.Regex("Version=(?<version>[0-9.]*)");
var m = versionExpression.Match(asmName);
string version = String.Empty;
if (m.Success)
{
    version = m.Groups["version"].Value;
}

Tags: ,