Thursday, August 15, 2013

Remote Controlled RoboTank

RoboTank and Gamepad

This is my version of the ever popular to build RoboTank. It uses an Arduino Mega 2560 with the AdaFruit motor shield and an XBee S1 to communicate to the DFRobot Gamepad. The sketch for the RoboTank makes use of the AFMotor.h to drive the motors and includes a serial parser to read and process the commands coming from the Gamepad.

Robotank-Sketch.zip
DFRobot Wireless Joystick

Monday, August 05, 2013

DFRobot Wireless Joystick 1.1 (DFR0182)

DFR0182

Wireless Joystick Sketch

Wireless Joystick Schematic

DFRobot Wiki Page

The DFRobot's Wireless Joystick V1.1 is similar in size and shape to an XBox controller.  The controller, or gamepad as it is also referred to, is an Arduino Deumilanove w/ATMega 328 and requires either an FTDI Basic Breakout or USB Serial Light Adapter to program.  The board uses 3.3V, when connecting either the FTDI or USB Adapter verify correct voltage is set on the adapter, via jumpers on the adapter, otherwise you will burn out the gamepad.

Wednesday, June 13, 2012

Excel User Defined Functions with C# and ExcelDna

Adding user defined functions to Excel can be laborious, either you use VBA or COM. Why can't Microsoft make it easier to use Visual Studio and .NET within Excel?

Enter ExcelDna.



This example creates a static function in C# using Visual Studio. There is documentation that already describes this, what I am adding is:

  • Use Visual Studio to create project
  • Post Build Events to help create the final XLL file.


NOTE: I hate Post Build Events. The ONLY exception is in this case where I am modifying the output of the final build. Post Build Events are Evil especially when used in a large development team. A better solutions is to create actual Build Scripts that do what I am about to do. You have been warned.

First, create a new Class Library project. Use NuGet to add a reference to the Excel-DNA package. NuGet will also add ExcelDna.dna and ExcelDna.xll to your project. Rename them both to the name that you want your final output xll to be. In my case I renamed them to Scratch-ExcelDna.dna and Scratch-ExcelDna.xll. Also for both files change to properties for Build Action to "Content" and Copy to Output Directory to "Copy Always".

Within the packages folder created by NuGet is the ExcelDnaPack utility, in the tools folder. This will package your project into one xll file. For it to work you need to update the .dna file:

<DnaLibrary RuntimeVersion="v4.0">
     <ExternalLibrary Path="DC.Scratch.ExcelDna.dll" Pack="true" />
</DnaLibrary>


Note that I am using .Net 4.

To get the pack utility to work, add a Pre-build event to delete the existing xll:

del "$(TargetDir)Scratch-ExcelDna-packed.xll"

Then add a Post-build event to recreate it:

"$(SolutionDir)packages\Excel-DNA.0.29\tools\ExcelDnaPack.exe" "$(TargetDir)Scratch-ExcelDna.dna"

While you are in the Project Properties messing with the evil build events set the Debug options so you can test your code. Set the External Program to you MS Excel and add a Command Line argument with a path to your final xll file.

Now, add a class TestFunctions:
[csharp]
using ExcelDna.Integration;

namespace DC.Scratch.ExcelDna
{
public class TestFunctions
{
[ExcelFunction(Description = "Product of two numbers", Category = "DNA Test")]
public static double TheProductOf(double x, double y)
{
return x*y;
}
}
}
[/csharp]

Hit F5 and see if Excel Starts. If it does, add some numbers to the Excel spreadsheet and see if the TheProduct() function works.

Download sample project here: DC.Scratch.ExcelDna

Microsoft should really look at buying Excel-DNA and incorporating it into Visual Studio. You Guys Listening!?!

Tuesday, May 22, 2012

Using Sencha Architect to Create Grafted Tree

Clint Harris posted How To Use ExtJS 4 TreePanels with Both Static Data and Model Stores. He has a great explanation of how to "graft" branches onto an ExtJS TreeView. In his example he is creating an Admin tree form that gives him access to Settings and Users.

I recreated his project using Sencha Architect 2.

The trickiest part was getting the tree to load the data correctly. I used the onLaunch function of the controller to get access to the TreeStores in order to call the userStore.setRootNode() and then to append the userStore to the settingsTreeStore.

Notice how I am using this.getUserTreeStoreStore() and this.getSettingTreeStoreStore(). Yes, I had to use "StoreStore" because I named my stores UserTreeStore and SettingTreeStore, then the Controller tacks on the second "Store" when it creates the get function.

Ext.define('GraftedTreeApp.controller.TreePanelController', {
 extend: 'Ext.app.Controller',

 models: ['UserModel'],
 stores: [
 'SettingTreeStore',
 'UserTreeStore'
 ],

 onLaunch: function() {
  var userStore = this.getUserTreeStoreStore();
  userStore.setRootNode({
   text: 'Users',
   leaf: false,
   expanded: false
 });

  // Graft our userTreeStore into the settingsTreeStore. Note that the call
  // to .expand() is what triggers the userTreeStore to load its data.
  var settingsTreeStore = this.getSettingTreeStoreStore();
  settingsTreeStore.getRootNode().appendChild(userStore.getRootNode()).expand();
 }

});



Pretty much everything else was setting properties in the Sencha Architect UI. The project files are here.

NOTE: There is a known bug in this solution, when you collapse and expand the User node it loads more User data, after which the User node cannot be collapsed.

Monday, March 26, 2012

C# Spirograph Point Generators

Spirograph's  are cool.  See here and here.



I put together three ways to generate points for a Spirograph, first using a Brute Force straight generate the points, second using a Parallel.For and third using LINQ.

Monday, October 31, 2011

FileSystemWatcher With the BlockingCollection

While working with the FileSystemWatcher I found that if too many files were created the built in buffer will overflowed and files will be skipped.  After much research I found out about the Producer-Consumer Problem.  Then I found that .Net 4 has the BlockingCollection which helps solve the issue.  But how to use it with the FileSystemWatcher?

On StackOverflow I found Making PLINQ and BlockingCollection work together.  I'm not so interested in the PLINQ issue but this is a great example of using The BlockingCollection with FileSystemWatcher.

[csharp]
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;

namespace ConsoleApplication4
{
    public class Program
    {
        private const string Folder = "C:\\Temp\\InputData";

        static void Main(string[] args) {

            var cts = new CancellationTokenSource();
            foreach (var obj in Input(cts.Token))
                Console.WriteLine(obj);
        }

        public static IEnumerable<object> Input(CancellationToken cancellationToken) {
            var fileList = new BlockingCollection<string>();

            var watcher = new FileSystemWatcher(Folder);
            watcher.Created += (source, e) => {
                if (cancellationToken.IsCancellationRequested)
                    watcher.EnableRaisingEvents = false;
                else if (Path.GetFileName(e.FullPath) == "STOP") {
                    watcher.EnableRaisingEvents = false;
                    fileList.CompleteAdding();
                    File.Delete(e.FullPath);
                } else
                    fileList.Add(e.FullPath);
            };
            watcher.EnableRaisingEvents = true;

            return from file in
                       fileList
                            .GetConsumingEnumerable(cancellationToken)
                            .AsParallel()
                            .WithMergeOptions(ParallelMergeOptions.NotBuffered)
                            .WithCancellation(cancellationToken)
                            .WithDegreeOfParallelism(5)
                   let obj = CreateMyObject(file)
                   select obj;
        }

        private static object CreateMyObject(string file) {
            return file;
        }
    }
}
[/csharp]

Wednesday, September 28, 2011

Running Totals in Excel

Excel does not have a running total feature or function built in.  All the examples I found on the web to do running totals included VBA code. Not that I have anything against VBA but I thought there should be a way to do running totals with built in worksheet functions.

Enter our one of our favorite functions: OFFSET().  But first, what is a running total?

Running Total Example

A running total is when you have a list of Values and you want to total of the current Value with the Previous values.  Wikipedia states that a running total is "summation of a sequence of numbers which is updated each time a new number is added to the sequence, simply by adding the value of the new number to the running total."

The key to getting the SUM() correct is getting the Range correct.  For a given Range of Values, start with the First number and SUM() until you get to the current row.  You can do this by using the OFFSET() function and taking advantage of Excel's table features to get the column range.

[vb] OFFSET ( cell reference, rows, columns, [ height ], [ width ] ) [/vb]

In the above case the Running Total column's formula becomes:

[vb] =SUM( OFFSET( [Values], 0, 0, ROW() - ROW([Values]) + 1, 1 ) ) [/vb]

[Values] is the Column we want the running total for.

rows = 0 and columns = 0 because we want to start at the very first cell of [Values]

[width] = 1 because we want only the [Values] column

[height] = ROW() - ROW([Values]) + 1, this is the magic line.

To get the height we have to figure out our current Row number, subtract off the starting Row of [Values] then add 1.  ROW([Values]) gives us the starting row of the column and ROW() gives us the current row.  For example, if the Table starts on row 3 (headers are on row 3) then the column [Values] starts on row 4.  The height of the very first cell in [Values] is:

[vb] ROW() - ROW([Values]) + 1 = 4 - 4 + 1 = 1 [/vb]

The height of the 3rd cell in the [Values] column is:

[vb]ROW() - ROW([Values]) + 1 = 6 - 4 + 1 = 3 [/vb]

Offset Function in Excel

Running Total

Tuesday, January 18, 2011

Scratching Parallel with StopWatch

Threw together a quick parallel stopwatch test. Not sure if the times prove anything.

[csharp highlight="28,33,39"]
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Scratch.ParallelProcessing
{
class Program
{
static void Main(string[] args)
{
const int count = 10000000;
var source1 = Enumerable.Range(0, count).ToArray();
var source2 = Enumerable.Range(0, count).ToArray();
var source3 = Enumerable.Range(0, count).ToArray();

Stopwatch stopwatch = new Stopwatch();

var parallelElapsedTimes = new List<TimeSpan>();
var linearElapsedTimes = new List<TimeSpan>();
var linqSelectElapsedTimes = new List<TimeSpan>();

for (int i = 0; i < 10; i++)
{
stopwatch.Reset();
stopwatch.Start();
var parallelResults = Parallel.ForEach(source1, s => s %= 2);
parallelElapsedTimes.Add(stopwatch.Elapsed);
stopwatch.Reset();

stopwatch.Start();
LinearAction(source2, s => s %= 2);
linearElapsedTimes.Add(stopwatch.Elapsed);
stopwatch.Reset();

stopwatch.Reset();
stopwatch.Start();
Array.ForEach(source3, s=>s = s%2);
linqSelectElapsedTimes.Add(stopwatch.Elapsed);
stopwatch.Reset();

}

Console.WriteLine("Elapsed Time\t\tMin\t\tMax\t\t\tAvg");
Console.WriteLine("============\t\t===\t\t===\t\t\t===");
Console.WriteLine("{0}\t\t{1}\t\t{2}\t\t\t{3}", "Parallel", parallelElapsedTimes.Min(t => t.Milliseconds), parallelElapsedTimes.Max(t => t.Milliseconds), parallelElapsedTimes.Average(t => t.Milliseconds));
Console.WriteLine("{0}\t\t\t{1}\t\t{2}\t\t\t{3}", "Linear", linearElapsedTimes.Min(t => t.Milliseconds), linearElapsedTimes.Max(t => t.Milliseconds), linearElapsedTimes.Average(t => t.Milliseconds));
Console.WriteLine("{0}\t\t\t{1}\t\t{2}\t\t\t{3}", "Linq", linqSelectElapsedTimes.Min(t => t.Milliseconds), linqSelectElapsedTimes.Max(t => t.Milliseconds), linqSelectElapsedTimes.Average(t => t.Milliseconds));

}

public static void LinearAction<T>(IEnumerable<T> source, Action<T> action)
{
foreach (var s in source) action(s);
}
}
}


[/csharp]

Results of the timer:

Elapsed Time Min Max Avg
============ === === ===
Parallel 63 191 79.5
Linear 138 143 140.3
Linq 54 56 54.5
Press any key to continue . . .


I'm running 64 bit Vista on a Intel Core2 Duo with 4GB RAM. The Parallel seems to be inconsistent, and depends a lot on whether or not it grabs that second CPU.

Monday, January 10, 2011

Simple MapReduce

Open file, read in lines, return individual words, get length of each word, Order by the length of the words, count each word of specific length.

[csharp]

static void Main()
{

var counts = OpenFileReturnWords(@"LoremIpsumDolor.txt")
.AsParallel().Select(w=>w.Length)
.AsParallel().ToLookup(k => k)
.Select(c => new { Number = c.Key, CountOfNumber = c.Count() })
.OrderBy(c=>c.Number);

foreach (var count in counts)
Console.WriteLine("Count of {0:0000}: {1}", count.Number, count.CountOfNumber);

Console.WriteLine("Total Count: {0}", counts.Sum(c=>c.CountOfNumber));
}

public static IEnumerable<string> OpenFileReturnWords(string fileName)
{
using (var reader = new StreamReader(fileName))
{
string line;
while ((line = reader.ReadLine()) != null)
{
var wordsInLine = line.Split(new[] {' ', '.'})
.Where(word => !string.IsNullOrEmpty(word));

foreach (var word in wordsInLine)
yield return word;
}
}
yield break;
}

[/csharp]