Sunday, October 18, 2009

You down with OPC?

What a weekend. Who knew it was such an issue to work out a serial protocol in Visual Basic? (Actually, as it turned out, it wasn't as big an ordeal as I was trying to make it.)

Let's recap the status quo. I have an Arduino Duemilanove microcontroller board that I'm trying to use as a low-budget PLC. I have three Dallas Semiconductor DS18B20 digital thermometers hooked up via the One-Wire wiring topology. I also have two solid-state relays (SSRs) that I will use to switch line voltage to various devices. I need a way to read the temperatures from the thermometers and modulate the SSRs from a "traditional" manufacturing environment like, for instance, GE Intelligent Platforms' Proficy Workflow.

The best way to do that is to use the industry standard for connecting to devices, namely OPC. The trick is that my homebrew (no pun intended) microcontroller doesn't have a driver for anybody's OPC server environment, so I have to create one. To complicate matters, I have to do it using tools that I can afford.

Lots of vendors offer trial versions of their OPC server toolkits. Most of those trial versions are time limited, in that they either only work for some trial period (like 30 days) or they only work for a short interval without requiring a restart (like 2 hours). Fortunately, has a listing of lots of OPC server vendors, and I found one that had a toolkit with a tag limited demo instead of a time limited one. The software comes from Graybox (at and I would recommend that you check them out if you're looking for a .NET based OPC server solution. (Some of you who know me are probably asking "has the Unix geek turned coat? .NET? Really?" The sad fact of the matter is that OPC is a Windows technology - the organization that controls the standard has "retronymmed" OPC to mean Open Process Connectivity or some such BS but its original name was "OLE for Process Control." So to make it work you have to use a Windows environment, more's the pity.)

Fortunately Graybox provides some sample code with their OPC server toolkit. This is important because I have not had an original thought in my life but I can copy with the best of them. I built the sample server in Visual Studio 2008 and it ran fine, so I moved on to the significant work - making the sample server talk to my controller. To quote a former colleague, "it's just a simple cereal link" - how hard can it be?

Famous last words. In the end it was simple. Getting there was complicated. I struggled for a while with a confusing phenomenon: when I hooked up a terminal emulator to the com port I could get the exact expected results, but when I tried to use Visual Basic I would only get the response about once every four commands. (This was way before I tried to use the OPC software. I was just trying to build a simple command-line based interface to prove I could do the serial I/O correctly.)

After several hours of frustration and debugging, I finally figured it out by having the Arduino echo the commands received from the serial port onto the LCD display I hooked up to it. When I did that, the problem was clear, and in hindsight obvious: Windows terminates a line with a CR-LF pair, and real operating environments only use LF. (Well, let me qualify that. VMS used a different technique for ending records.) The WriteLine() function used in Windows sends a CR-LF, but the I/O reader on the Arduino was only expecting an LF. What was happening was that after the first successful command from the Windows program, it took four iterations for the Arduino's input buffer to realign (because of the extraneous CR in each iteration). Once I realized that, I changed the Windows-side I/O to use Write() instead of WriteLine() and things started working more effectively.

The last challenge was the actual OPC server code itself. The big problem here was a basic misunderstanding on my part concerning the .NET and Windows security models. Evidently you can't do operations in a class constructor if they require privilege. Including things like opening a serial port. My OPC server kept throwing exceptions on the port open command, telling me I didn't have sufficient privilege. I thought that odd considering I was logged in as the local administrator. Something I Googled made me move the Open() command out of the constructor into a separate method, and that resolved the issue.

As of now I have an OPC client running and getting periodic updates from the Arduino. The tags are available, and I'm ready to move the code to the Proficy Workflow server so I can get on with the next phase of the project.

Maybe I should call Jumpin' Jack Flash

It looks like I may have leaked out my CO2 again. The primary regulator is only showing 10 PSI. I suspect there's an issue with the high-pressure gauge in that assembly. It never read 0 PSI even when it was disconnected, and I had to whack it to get it to register the new cylinder's pressure when I changed it last week. I think I will just stick a plug in there. I'd hate to have to buy another regulator. because...

10 gallon batches are coming

I got an 80 quart pot so I can ramp up production to 10 gallon batches. It arrived Friday, but I have yet to boil anything using it to build up its oxide levels. I don't have enough grain on hand to run a 10 gallon batch of anything except Gayle Bait. I will order up some more stuff and brew later this week. (Hopefully.)

1 comment:

  1. I learn about OPC too,
    I still confuse about data packet when the OPC server talk to OPC client. and the data packet from OPC client to OPC server.

    I am try to use Wonderware as OPC server.
    and ATMEL AVR microcontroller as OPC client.

    this time I still searching example C or BASIC code that must implement to the microcontroller.

    please give me some advice.