February 2009 Entries

Relay code in action

induction load test

Tested the first induction suppressing circuit. 

Induction Load Test by you.

Without the the little circuit that is resting on power supply, the 2nd relay board would have froze.  I was opening and closing the valve to my heart’s content.  Heck yeah!  Now to create at a minimum 7 of them as that is how many food valves I have.  I have 4 done and 17 circuits prepped to be made.

I’ll create a cool demo of the circuits now with compressed air now I know I can open and close without failure.

Now that I have that crossed off my list, now I need to buy a touch screen now that I can use with a finger on the cheap.

Mix Master Threading

cocktail So in a bar, you can have someone pour multiple liquids at once or do one liquid after another.  Most can be poured all at once however.  So they can be poured asynchronously.  Designing the system to do one or the other style pour is rather easy.  Mixing the two caused a bit of a headache much like drinking too much.  A drink example that uses this case is a long island ice tea.  You need a few types that can be poured at once then you end it with a splash of coke.

So how to solve this?

Since we’ll need thread to open multiple relays at the same time and creating threads is expensive, we’ll use a ThreadPool object to help manage and keep old threads alive.  Reusing threads is not just nice, it is the American way of life.  Just remember that.

Another massive thing to remember is finding out what resources are thread safe.  MSDN will tell you at the bottom what is thread safe.

First we’ll set up all the toys we’ll need to set this up, some AutoResetEvents, an int, bools, some Mutex, and a Semaphore.  Yes this is a lot of stuff. 

A mutex?  semaphore?  AutoResetEvent?  muh?  If you can’t remember what these toys are, I’ll explain using a line to get into a bar analogy.  

  • Mutex: Kind of like a bouncer.  It makes sure the path to the floor is clear, if it isn’t, it won’t let you get in.
  • Semaphore: Allows only so many in to party at the same time.
  • AutoResetEvent: You get a buzzer that tells you when you are cool enough to enter.  When you get enough girls to get in, your buzzer goes off and you’re allowed in.  Until then, stand out in the cold.  Similar to a mutex, but different.

If you need extra help, I suggest checking out Wikipedia, they’ll have some helpful demos, so will MSDN.

Code:

public delegate void RelayEventHandler(object sender, RelayCommand e);
public event RelayEventHandler RelayStartedEvent;
public event RelayEventHandler RelayExecutedEvent;

readonly Semaphore _pool = new Semaphore(1, 1);
readonly AutoResetEvent sequentialWorkWait = new AutoResetEvent(true);
readonly AutoResetEvent asyncToSequentialWorkWait = new AutoResetEvent(false);
readonly Queue<RelayCommand> commands = new Queue<RelayCommand>();
readonly Mutex writingToComport = new Mutex();
readonly Mutex addingItemsToQueue = new Mutex();

bool doingWork;
bool asyncWorkMode;
int concurrentWorkers;

This entire code is broken up in three methods:

  • AddCommand
  • processQueue (Singleton thread)
  • doWork (multithreaded)

Now lets add stuff.  We need to use a mutex to be sure commands are added in the proper order.  This may be overkill but better safer than sorry.  With a Mutex, you call WaitOne() to signal you’re in a critical area of shared code and only you can have access to it.  All other threads must wait until ReleaseMutex() is called.  With WaitOne, you can set a timeout, in my instance, I’m not because I trust I coded this properly.

public void AddCommand(params RelayCommand[] Commands)
{
	addingItemsToQueue.WaitOne();

	foreach (RelayCommand command in Commands)
		commands.Enqueue(command);

	addingItemsToQueue.ReleaseMutex();

	if (!doingWork && commands.Count > 0)
		ThreadPool.QueueUserWorkItem(processQueue);
}

Now instead of showing the queue processing function, we’ll switch to the worker function.  This can actually be altered to whatever you need by swapping line 7 to 9 and changing what state object you pass in.

  1. If the UI needs to know when work has started, it will be notified.
  2. We do work
  3. Subtract the amount of concurrent workers we have
  4. If the command is sequential, we’ll signal we’re all done so the next call can happen
  5. If the command is asynchronous but we’ve queued up a sequential call, we’ll check to be sure all work is done, if so we’ll signal the sequential work can now start as all asynchronous work has completed.
  6. If the UI needs to know when work has finished, it will be notified.

private void doWork(object state)
{
	if (state == null) return;
	
	var command = (RelayCommand)state;

	if (RelayStartedEvent != null)
			RelayStartedEvent.Invoke(this, command);

	On(command.Bank, command.Relay);
	Thread.Sleep(command.Milliseconds);
	Off(command.Bank, command.Relay);

	concurrentWorkers--;

	if (!command.Asynchronous)
		sequentialWorkWait.Set();
	else
		// now signaled to be in async mode 
		// and all async'ed work is done
		if (!asyncWorkMode && concurrentWorkers == 0)
			asyncToSequentialWorkWait.Set();

	if (RelayExecutedEvent != null)
		RelayExecutedEvent.Invoke(this, command);
}

Now the heavy lifter, the queue processor.  Since we are using a ThreadPool, we want to be utterly sure only one processor is happening else stuff may get weird, so for this we use a Semaphore.  I actually think the code comments do a good job of explaining what is going on and why.  If not I’ll go in and explain further.  I have the doingWork Boolean just to prevent extra threads from being created for no reason if more commands are being added while work is being done.

private void processQueue(object state)
{
	// force only one of these types of thread procs
	// to execute at any time
	_pool.WaitOne();
	doingWork = true;
	var firstWorkerLoop = true;
	while (commands.Count > 0)
	{
		var command = commands.Dequeue();
		// can't pop until inside loop
		if (firstWorkerLoop)
			asyncWorkMode = command.Asynchronous;

		firstWorkerLoop = false;
		if (!command.Asynchronous)
		{
			if (asyncWorkMode)
			{
				asyncWorkMode = false;
				asyncToSequentialWorkWait.WaitOne();
				// after every sequential call, we reset to blocking
				// need to allow this to continue
				sequentialWorkWait.Set();
			}

			sequentialWorkWait.WaitOne();
			// on next loop, thread will wait now
			sequentialWorkWait.Reset(); 
		}
		else // asynced
		{
			if (!asyncWorkMode)
			{
				// have to wait for current pour to finish.
				sequentialWorkWait.WaitOne();
				// have to reset so sync will wait for
				// all async to finish
				asyncToSequentialWorkWait.Reset(); 
			}

			asyncWorkMode = true;
		}

		concurrentWorkers++;
		ThreadPool.QueueUserWorkItem(doWork, command);
	}
	doingWork = false;
	_pool.Release();
}

Who knew making mixed drinks could involve mutually exclusive resources?

induction load suppressors

IMG_5461

Since my relay boards dislike high induction loads, I had to build a suppressor to reduce the shock of getting turned on.  Yup, it is just a giant capacitor.

The Bluetooth board works fine but the XR expansion board disliked the spike, so these are getting added everywhere.  I have to see what is the best way to implement them so the wiring is stylish and the circuits are protected.

Won’t get to test working versions until Thursday due to work.

Giving Credit for helping

For the Windows Mobile TopMostForm class I wrote, I had a bit of help.  I found out the person who helped me out has a blog so I’m going to give him the proper credit due.  Reed Robinson helped provide both a native and the framework for the the managed code way to do it.  Thanks a ton!

Now lets create some really annoying applications that can be above literally everything.

Mo Relay boards, Mo Problems

I hung my head in shame as I gave up on my old relay boards and ironically went back to the same company I started with, Control Anything.  Now that I’m DC for the relays and using their Bluetooth model and an expansion board.  So part number wise, I got a BTADR85ProXR (Bluetooth master, 8 channel, 5 Amp SPDT Relay board) and a XR165 (slave, 16 Channel, 5 Amp SPDT relay board).  The nice thing about their boards and Bluetooth is it mounts as a serial port AND is wireless so I can’t blow up another laptop.

While I do have the c# relay board file still, I think it needs some work to make it work far better.  I think I may shift to a queue (first in, first out) for commands.  Due to the massive difference in commands, I needed to change a few things.  On the Robotic Connection boards, everything was timer based, with Control Anything boards, I control the timing.  They do have timers onboard, however their documentation has a warning precision worries me.

New UI for relay board tester:
image

Another big change I did with the source is changed it to a very simple metaphor for operating the API.  Stuff typically turned stuff ON or OFF so I changed stuff from AllRelaysOnBank, AllRelaysOn, and RelaysOn to what you see below.  I found a new command that may cause an issue but overall, I think this works nicely.  Simple and clean, like snow.  Snow hides all.

Some code from my refactored / tweaked Control Anything class:

public bool On()
{
	write(new byte[] { startCommand, 130, 0 });
	return success();
}

public bool On(int Relay)
{
	write(new [] { startCommand, (byte)(Relay + 8) });
	return success();
}

public bool On(int Bank, int Relay)
{
	toggleRelayCommand(Bank, Relay, true);
	return success();
}

private static void toggleRelayCommand(int Bank, int Relay, bool TurnOn)
{
    Relay += 100 + ((TurnOn) ? 8 : 0);
	write(new [] { startCommand, (byte)Relay, (byte)Bank });
}

private static void write(byte[] bytes)
{
	ComPort.WriteBuffer(bytes);
}

private static bool success()
{
	return success(85);
}
private static bool success(int successCode)
{
	var temp = ComPort.ReadBufferChar();
#if DEBUG
	Console.WriteLine(temp);
#endif
	return (temp == successCode);
}

Rise my winmo form, be above everything

image

DISCLAIMER: This was tested on Windows Mobile Standard (no-touch), not WinMo Professional (touch screen).  It *should* work still.

I’m creating a small application that will get me out of countless situations I don’t want to be in.  I had one key issue with Windows Mobile that I had to overcome.  The password screen, lock screen, whatever you want to call it.  Here is a screen shot so we’re all on the same page.

Now why would someone need to pop above this screen?  Well, if your application sleeps or does work in the background while other things happen.  Now due to corporate policy, my phone is forced to be locked with a password.  Prior to this, I would still have my phone locked if it wasn’t being used automatically to help prevent pocket dial.

This involves a few pinvoke calls to accomplish this.  I also suggest wrapping this into its own class and let other forms inherit from it.

If you want a quick download, here is the zip for the top most form that will appear above a lock screen.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace pNerd.Core.Mobile
{
	public class TopMostForm : Form
	{
		private const int GWL_STYLE = -20;
		private const int WS_EX_ABOVESTARTUP = 0x20000000;
		private const int WS_EX_TOPMOST = 0x00000008;

		[DllImport("coredll.dll", SetLastError = true)]
		private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
		[DllImport("coredll.dll", SetLastError = true)]
		private static extern bool UpdateWindow(IntPtr hWnd);
		[DllImport("coredll.dll", SetLastError = true)]
		private static extern bool IsWindow(IntPtr hWnd);
		[DllImport("coredll.dll", SetLastError = true)]
		private static extern bool SetForegroundWindow(IntPtr hWnd);

		public TopMostForm()
		{
            hWnd = Handle;
			myTimer = new System.Threading.Timer(FocusCallback, 1, 0, 100);
			TopMost = true;
		}


		readonly System.Threading.Timer myTimer;
		readonly IntPtr hWnd = (IntPtr)0;

		private void FocusCallback(object state)
		{
			if (!IsWindow(hWnd))
				return;

			SetWindowLong(hWnd, GWL_STYLE, WS_EX_ABOVESTARTUP | WS_EX_TOPMOST);
			SetForegroundWindow(hWnd);
			UpdateWindow(hWnd);

			// destroy timer
			myTimer.Dispose();
		}
	}
}

Since we need the window’s handle, we’ll store that in a global variable.  We’ll use a threading timer to call a function right after the form’s construction to do the rest.  First we’ll verify the handle is an actual window.  Then we’ll call a pinvoke that will set some windows styling to be the topmost and force it to start above.  Then we’ll force it to be the focused window.  To finish it up, we’ll update the window and then destroy the timer to save processing power and increase battery life.

If you don’t understand what I was talking about with inheriting the form you want to be topmost, do this.

Original code:

public partial class YourForm : Form
{ /* code */ }

Changed to this:

public partial class YourForm : TopMostForm // use to be Form
{ /* code */ }

Download: TopMostForm.zip on PeaceLoveCode.com.