Thursday, July 22, 2010

Turn off the pesky internal speaker

One of my new projects has a pesky alarm that goes off through the internal speaker. When you're debugging and forcing errors on it, it drives the whole office crazy. Luckily, there's a way to turn off your internal speaker in Windows XP!

  1. Load up System Properties (start+pause break, or Control Panel>System)
  2. Go to the Hardware tab
  3. Press the Device Manager button
  4. In the drop down menu at the top, choose View>Show Hidden Devices
  5. In the window below, an option appears called Non-Plug and Play Devices
  6. One of the options will be Beep.
  7. Right click, choose Disable.
  8. Restart your computer if it asks
All annoyances gone!

Friday, July 2, 2010

Axis Camera Control

For my live image processing, I tend to use Axis products. Their cameras provide the images as a motion JPEG stream via Ethernet, while their video servers can convert full PAL/NTSC video to motion JPEG streams via Ethernet. It's handy, no real video converters required. Just plug your computer onto the same network as cameras, and bam!

There's a few way to get the images. Individual images can be accessed using an HTTP request:
http:///axis-cgi/jpg/image.cgi?resolution=704x576&camera=1
If you wanted to do that in C#:
System.Net.HttpWebRequest myReq;
System.Net.HttpWebResponse myResp;
myReq = (System.Net.HttpWebRequest)(System.Net.WebRequest.Create("http://136.18.33.16/axis-cgi/jpg/image.cgi?resolution=704x576&camera=1");
myReq.Timeout = 500;
myResp = (System.Net.HttpWebResponse)(myReq.GetResponse());
Bitmap bmp = new Bitmap(Image.FromStream(myResp.GetResponseStream()));
Easy. For easy access of motion video, Axis has provided the handy AxAxisMediaControl as part of their Windows SDK.

I've been using this for years, but have recently noticed a few problems. The main one being that the camera control has to always be visible in your form, otherwise it will just loop the last received image. So no screensavers, the program has to always be on top, and don't even think of hiding the Axis control (which is what I did, I wanted to hide the live stream). Also, to get the image into C# required some memory manipulation and even then the images were coming in upside down.

Despite trolling through the forums and support, there's no fix for this. It seems like I'm not the only one. Now this was a problem for me. I had a safety-critical program that was analysing 15+ frames a second 24 hours a day and could not be turned off. However, we needed to lock the computer up so that no one else could access the computer. Once we locked up the computer, the whole thing stopped working.

I tried work around, I tried accessing the image frame by frame using the HTTP request, but it was too slow. So in frustration, I created my own custom AxisCameraControl (download the code here).

Although not as complete as the Axis one (there's no audio or PTZ) it's perfect for receiving just motion JPEG streams. It has support for
  • multiple camers for video servers
  • password protected devices
  • limiting of maximum frame rate
  • different video sizes
  • autoreconnect on stream loss
  • limiting JPEG compression
The control is not a visible control, unlike the Axis one. It is more of a background threaded class. It has a lot of the same options as the original Axis control, but the following are always required:
public string IP;
public int Width;
public int Height;
public int Framerate;
When running (by calling public void Start()), a worker thread runs in the background. It opens up a motion JPEG stream to the device and looks for the start of each image. At this point, I have to credit/thank http://www.codeproject.com/KB/audio-video/cameraviewer.aspx for providing me with the motion JPEG code.

Once an individual JPEG is decoded from the stream, it throws an event.
Bitmap bmp = (Bitmap)Bitmap.FromStream(new MemoryStream(buffer, start, stop - start));
AxisArgs ax = new AxisArgs(bmp);
OnNewImage(this, ax);
The argument for the event (AxisArgs) is a Bitmap, allowing the image to be passed by value, not by reference like the old Axis control. After all of this, the image is disposed and everything is started again.

Usage in a program is fairly easy:
AxisCameraControl.Camera axisCameraControl1 = new AxisCameraControl.Camera();
axisCameraControl1.IP = "136.18.33.16";

axisCameraControl1.Width = width;
axisCameraControl1.Height = height;
axisCameraControl1.Framerate = frameRate;
axisCameraControl1.OnNewImage += new AxisCameraControl.Camera.NewImage(axisCameraControl1_OnNewImage);
if (!axisCameraControl1.IsPlaying())
axisCameraControl1.Start();

void axisCameraControl1_OnNewImage(object sender, AxisCameraControl.AxisArgs args)
{
Bitmap bmp = new Bitmap(args.Image());
//do something with bmp
pictureBox1.Image = bmp;
}
Simple! And it doesn't have to be visible to work. I've been testing this for the last month, and so far there seems to be nothing wrong with it. I've got a lot more work to do before it has the same functionality as the original AxAxisCameraControl, so I will update as it progresses.

Download the C# camera control class

Bugs:
  • On some servers, can take a few seconds to get the image started
  • If updating to a pictureBox with a high frame rate, the maximum frame rate drops dramatically for large images. Better to update pictureBox with an image every few frames for a frame rate over 8 FPS at an image size greater then 640x480

Thursday, July 1, 2010

RSLinx v Windows XP SP3

I'm in charge of a little, fully automated system that has it's own PLC and computer interfacing to it. The computer runs RSLogix 500/RSLinx and it communicates with a MicroLogix 1500 PLC.

The computer recently imploded (quite literally), so I migrated everything over to a new computer we had lying around. Everything was installed and running nicely in the office, I sent it off to site (in another state) to install the new PC, but we could not communicate with the PLC.

According to my site contact, the error we kept getting was something like (she spelt it out over the phone to me, it won't be exact):
initDriver failed code:-1
parentdriver (linx gateway may not be running)
After a few hours on the phone with Rockwell (we didn't have the tech support package, which made it difficult), I learnt something amazing.

RSLinx cannot communicate to devices using Windows XP SP3. Amazing. Our PC was recently rolled back from Windows 7 to XP, and I guess it was SP3 that was installed. Everything else works beautifully, but the RSLinx communications drivers (at least for Ethernet) will not.

So now I'm trying to figure out how to roll back to SP2 without losing anything. I'll keep you posted