BACnet Meeting in Albuquerque

July 17th, 2010

I attended the recent BACnet meetings in Albuquerque, and in the process, learned to spell the city name!  I participated in the Lighting Applications working group, the Objects and Services working group, the BACnet SSPC, and the MS/TP working group.

One of the proposals that started in the MS/TP working group made it through the public review process, and was voted by our committee to be published!

The Journey of a Small BACnet Proposal

In typical bike shed fashion, a small change to the BACnet standard took a very long time to become a standard.  Here is the story.

In November, 2002, I proposed (my 13th proposal) to expand the allowable baud rates for MS/TP to include 57600 bps and 115200 bps.  When reviewing MS/TP in Clause 9, I noticed that the baud rates specified in 9.2.3 are rather limited, and the fastest one doesn’t work well on PC based UARTs (76800 bps).  Since PC based control was becoming more prevalent in 2002, it seemed appropriate to permit fast speeds for PC compatible UARTs.

Someone reviewed the proposal, and asked for some data regarding the maximum length of an RS-485 segment while running at 115,200 bps.  I searched for the best literature I could find on the subject, and ended up with an Application Note from National Instruments which contained a nice graph of Cable Length vs Data Rate for RS-485.

Unfortunately, there was not a table of data along with the graph. I found and quickly learned how to use Scilab, the free platform for numerical computation. I did some linear interpolation (curve fitting) based on points (red dots) from the graph (Scilab Script):

-->// Scilab 3.0
-->// data from the graph
-->// The data is linear, but the graph is logarithmic
-->t = [0.1 0.2 0.4 0.5 0.8 1.0];
-->y = [4000 2000 1000 800 500 400];
-->xyd = [t;y];
-->yi=exp(interpln(log(xyd),log(t)));
-->err = (y-yi)'
err  =
1.0D-12 *
!   0.4547474 !
!   0.2273737 !
!   0.2273737 !
!   0.1136868 !
!   0.1705303 !
!   0.1136868 !
-->tt = [0.1 0.1152 0.2 0.2304 0.4 0.4608 0.5 0.8 1.0];
-->yi=exp(interpln(log(xyd),log(tt)));
-->xyi = [tt ; yi]'
xyi  =
!   0.1       4000.     !
!   0.1152    3472.2222 !
!   0.2       2000.     !
!   0.2304    1736.1111 !
!   0.4      1000.      !
!   0.4608    868.05556 !
!   0.5       800.      !
!   0.8       500.      !
!   1.        400.      !

Since the graph was logarithmic, the points had to be converted.  Scilab took the points (t,y), created a table (xyd), interpolated (yi), checked the error of the curve for each point (err).  Then I added some standard baud rates to the list of points (tt), and did the same interpolation.  The result is the table (xyi) which includes .1152 (baud rate) at 3472.2222 feet.  I de-rated and used 3280 feet (1000 meters) as a safety margin.

I compiled the information into a revised proposal, and submitted the information to the working group in October, 2004.   At the April, 2005 Germantown meeting, the MS/TP working group voted this proposal up to the BACnet SSPC for review and future publication.

The document was discussed again at a subsequent MS/TP working group meeting in 2006, with concern raised over the reduced distance for the higher baud rate.  A consensus vote decided to eliminate 115,200 bps as a possible rate, leaving 57,000.  I revised the proposal to that effect in April, 2006, and it was voted up to the full SSPC BACnet Committee for review and future publication.

In October, 2008, there was a discussion of MS/TP baud rates on BACnet-L mailing list.  Coleman indicated that:

I’d like to get a proposal together that rewords the baud requirements in clause 9 of 135.  We’ve discussed 115200 several times in the MS/TP-WG, but I’m thinking something a little less contentious like making 38400 the default and making 9600, 19200, 57600, 76800, and 115200 optional.

Coleman sent a note to me indicating that he had modified the proposal again, mandating that 38400 be a default baud rate in addition to 9600.  I checked the venerable “BACnet Document Status Summary” which indicated that my proposal was still in MS/TP working group instead of SSPC.  Bummer.  It had been sitting around for years due to some missing communication.

I wrote to Coleman and said that I would prefer to leave my original proposal in the SSPC-135 queue as-is since it is more likely to be adopted sooner than later as it is now 3 years in the queue – and a case can be made that it has been sitting there awhile.  I suggested that another proposal with the additional mandatory baud rates would be better or could be discussed along with my proposal in the SSPC-135 meeting and added prior to a public review vote by SSPC-135.

My proposal finally made it to the floor of the Atlanta BACnet committee meeting in November, 2009, at the very end of the meeting.  After a short discussion, Coleman’s proposal was suggested to replace mine.  As meeting time was running out, David Fisher, convener of the MS/TP working group, “passionately insisted that [Coleman's proposal] will get a due amount of serious discussion time in Orlando. This proposal has been delayed unreasonably for years now.”

Coleman’s proposal was discussed at the next SSPC meeting in Orlando in January, 2010.  After a brief discussion and a minor revision, the proposal was voted to Publication Public Review as Addendum 135-2008ab. The pubic review period lasted from March 26 to May 10, 2010.  It received 2 comments requiring resolution, and 4 supportive comments (which do not require any action to be resolved).

One of the supportive comments suggested that we consider changing MS/TP timing delays when using the 115,200 baud rate in order to provide the fastest possible throughput when using the new speed.  It was decided to consider this request, and some analysis was done.  When we met in Abuquerque, in June, 2010, the analysis was presented as “no significant speed improvements could be made by changing the time delays.”  The BACnet committee voted to approve the public review comment responses, and since there were no substantive changes to the addendum, it is now published as an addendum to the BACnet standard.

BACnet and Software Patents

November 18th, 2009

I attended the BACnet Committee and working group meetings in November, 2009, in Atlanta, Georgia.  During the MS/TP working group meeting, it was disclosed that KMC had applied for a patent which invents automatic MAC addressing for MS/TP devices.  It was surprising and disappointing to me, since the BACnet MS/TP working group had been working on standardizing several mechanisms to allow automatic MAC addressing since early 2008.

Ubuntu Linux on Desktop PC

September 8th, 2009

I refurbished a couple of PCs for my family to use, and installed the latest Ubuntu Linux on them – Ubuntu 9.04 Jaunty.  I also updated my dual boot work computer with the latest Ubuntu – it was running Kubuntu and the latest Kubuntu is just foreign to me.

As is usually the case, adding additional packages is essential to getting the computer working right for me.

Add Codecs, Java, and other Customizations

The official way to do this is documented in the Ubuntu Wiki under CommonCustomizations. There is also a wiki page on EasyCodecInstallation. The official meta package is called “ubuntu-restricted-extras” and this installs:

  • MP3 playback and decoding
  • Sun Java runtime environment
  • Flash plugin
  • DVD playback
  • LAME (to create MP3 compressed audio files)
  • msttcorefonts (may be missing in kubuntu extras)
  • DeCSS script to download and install for DVD viewing

$ sudo apt-get install ubuntu-restricted-extras
$ sudo /usr/share/doc/libdvdread4/install-css.sh
$ sudo apt-get install msttcorefonts

Add the ability to compile, edit, and maintain code

Here are the compilers and their documents
$ sudo apt-get install build-essential subversion-tools gcc-4.2-doc glibc-doc manpages-dev
$ sudo apt-get install mingw32 mingw32-binutils mingw32-runtime
I need access to subversion and XSLT ChangeLog tools
$ sudo apt-get install subversion-tools
$ sudo apt-get install xsltproc
I install a couple of editors, useful for various things. Kate is already installed.
$ sudo apt-get install scite
$ sudo apt-get install vim-full
Useful tools for cleaning up code, converting comments and line endings, and code statistics:
$ sudo apt-get install splint
$ sudo apt-get install sloccount
$ sudo apt-get install indent
$ sudo apt-get install liwc
$ sudo apt-get install tofrodos

Add favorite online music source and music/video player VLC

$ sudo apt-get install streamtuner
$ sudo apt-get install vlc

Add the Adobe Flash Plugin and Sun Java JRE

A lot of websites use Flash or Java for their user interface, so it seems that they are essential.

$ sudo apt-get install adobe-flashplugin
$ sudo apt-get install sun-java6-jre

Get rid of annoying PC speaker beep

Using a console, remove the PC Speaker driver from the kernel:
$ sudo modprobe -r pcspkr
Create /etc/modprobe.d/blacklist-user.conf and add a line to keep the PC Speaker driver from automatically loading:

# Keep the annoying beep from occurring
# don't load the PC Speaker driver

blacklist pcspkr

SynapticsTouchpad

The laptop has a touchpad, which is really annoying when you also have a USB mouse attached, because the touchpad picks up thumps made by my big fingers and makes the mouse click somewhere that you didn’t want it to click.  Correcting this in Ubunut Jaunty is as easy as selecting System > Preferences > Mouse, under the Touchpad tab. Uncheck the Enable mouse clicks with touchpad check box.

AVR ISP mkII on Ubuntu Hardy

May 12th, 2009

BACnet Development Kit

I created a BACnet Development Kit, compiled the open source BACnet Protocol Stack hosted on SourceForge.net firmware using gcc-avr, and attempted to load the firmware onto the kit using an Atmel AVR ISP mkII USB programmer.  I connected the AVR ISP mkII to my Ubuntu Hardy Linux PC and attached the 2×3 ISP cable to the development kit board, and attempted to program using avrdude:

$ avrdude -c avrispmkII -p m644p -P usb -e -U flash:w:bacnet.hex
avrdude: usb_open(): cannot read serial number "error sending..."
avrdude: usb_open(): cannot read product name "error sending..."
avrdude: usbdev_open(): error setting configuration...
avrdude: usbdev_open(): did not find any USB device "usb"

Wow! That wasn’t nice.  A search on the Internet turned up some answers about how to fix the problem, and I modified my /etc/udev/avarice.rules file to look like this:

SUBSYSTEM!="usb_device", ACTION!="add", GOTO="avarice_end"

# Atmel Corp. JTAG ICE mkII
SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2103", MODE="660", GROUP="dialout"
# Atmel Corp. AVRISP mkII
SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2104", MODE="660", GROUP="dialout"
# Atmel Corp. Dragon
SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2107", MODE="660", GROUP="dialout"

LABEL="avarice_end"

I disconnected and reconnected my AVR ISP mkII, and tried again.  I still had the same results.  I checked that I was a member of the dialout group:

$ groups
skarg adm dialout cdrom floppy audio dip video plugdev users fuse lpadmin admin

I looked at the symbolic link in the /etc/udev/rules.d/ directory and also consumed the README file.  My file had the following name:

/etc/udev/rules.d/z60_avarice.rules

So I changed the filename:

$ sudo mv /etc/udev/rules.d/z60_avarice.rules /etc/udev/rules.d/60-avarice.rules

I unplugged the AVR ISP mkII, and plugged it in again.  I tried to run avrdude again:

avrdude -c avrispmkII   \
     -p m644p -P usb -e        \
     -U flash:w:bacnet.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e960a
avrdude: erasing chip
avrdude: reading input file "bacnet.hex"
avrdude: input file bacnet.hex auto detected as Intel Hex
avrdude: writing flash (57406 bytes):

Writing | ################################################## | 100% 6.31s

avrdude: 57406 bytes of flash written
avrdude: verifying flash memory against bacnet.hex:
avrdude: load data flash data from input file bacnet.hex:
avrdude: input file bacnet.hex auto detected as Intel Hex
avrdude: input file bacnet.hex contains 57406 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 5.41s

avrdude: verifying ...
avrdude: 57406 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

The kit programmed successfully, and began operation.

Wireshark and BACnet MS/TP

November 21st, 2008

I wrote an article about Analyzing BACnet with Wireshark for ASHRAE Journal special supplement BACnet Today.  ASHRAE is very particular about endorsing specific company products, and removed some references I had to information about how BACnet MS/TP can be supported on Wireshark by adding an external interface which sends Ethernet SNAP protocol packets.  The external interface was originally a Cimetrics U+4 device which connects BACnet MS/TP via USB to a computer, and uses a special driver to appear as a network interface to Wireshark.

In April, 2008, I was informed that the Cimetrics U+4 packets showed up in Wireshark, but were not decoded correctly.  I asked for a sample of the capture, and reverse engineered the header.  I then created the BACnet MS/TP decoding in Wireshark in order to display the MS/TP data, and passed the BACnet Network Layer and Application Layer information along to the existing dissectors.

The beauty of the BACnet protocol is that it is layered.  The NPDU (network layer) and APDU (application layer) encodings are the same regardless of the datalink layer used.  The NDPU layer is decoded by packet-bacnet.c, which passes the APDU layer to packet-bacapp.c.  The BACnet MS/TP datalink layer is decoded by packet-mstp.c which I created, and passes the NPDU, if it exists, to packet-bacnet.c, for decoding.  The ARCNET, Ethernet, and BACnet/IP (packet-bvlc.c) all pass a relevant packet to packet-bacnet.c for BACnet decoding.  I created packet-cimetrics.c for the Cimetrics header which passes the BACnet MS/TP datalink layer to packet-mstp.c.

The BACnet MS/TP patches were accepted into the Wireshark repository on May 13, 2008, checked in as SVN 25291.  The SVN 25881 was a fix to the Length decoding.  The BACnet MS/TP decoding eventually made it into the Wireshark 1.1 development release, but is not present in the Wireshark 1.0 stable release.

Wireshark now sees packets with the Cimetrics U+4 signature encapsulated in the SNAP protocol as MS/TP packets, and it is able to open a file that has been saved in PCAP format using the MS/TP WTAP signature.  But I didn’t have a Cimetrics U+4 device.  So I used a standard RS485 converter, my open source BACnet stack, and wrote a simple application to packetize the MS/TP frames and saves them to PCAP format.  I could now capture MS/TP packets and view them!

In August, 2008, I received an email from John in New Zealand.  His intention was “to use an existing simple VB application that captures MS/TP traffic from a low cost USB to RS-485 converter, to send the MS/TP packets using Winsock/UDP to Wireshark for final dissection and display.”  I figured that we could do this by making use of the existing SNAP protocol dissector that I created for the Cimetrics packets.

I reused the code that I had written to save in PCAP format, and wrote a simple application to packetize the MS/TP frames and resend them on Ethernet as the Cimetrics U+4 signature encapsulated in the SNAP protocol.  I got it to work under Linux, but would probably need to use WinPcap to get it to work under Windows.

Sending those SNAP protocol packets on Ethernet allows the display of BACnet MS/TP packets in realtime alongside BACnet/IP and BACnet Ethernet.  This makes it very easy to relate traffic going to and from workstations and routers with what is happening on the BACnet MS/TP network.

There are some sample captures (see cimetrics_mstp.pcap and mstp_wtap.cap) that demostrate some of the abilities of Wireshark.

I use a USB to RS-485 converter from SerialGear USB-COMi-SI-M, and am told that the B&B Electronics USOPTL4 works very well.  I am also told that the USB to RS-485 adapters that use the FTDI chipset are great for this as they allow the use of 76800 baud which is usually the stumbling block for native MS/TP interfacing with a standard PC serial port.

GIMP: Removing Noise from Digital Photos

October 29th, 2008

I shot some low light photography at the youth group Halloween dance using a Casio Exilim point-n-shoot, and some of the photos had digital noise, or grain (as we called it in the days of film).

I searched the internet for some assistance in removing the digital noise using the GNU Image Manipulation Program (GIMP), and stumbled upon a well written post about how to remove digital noise.  The technique makes use of the GREYCstoration plugin for the GIMP.

I use the GIMP on Kubuntu Linux, and wondered if there was already a package created for GREYCstoration.

$ apt-cache search greyc
gimp-plugin-registry - A repository of optional extensions for The GIMP

I found it!  So I installed it:

$ sudo apt-get install gimp-plugin-registry

After restarting the GIMP, here are the results:

Low light photo (scaled)

Low light photo (scaled)

Low light photo (GREYCstoration, scaled)

Low light photo (GREYCstoration, scaled)

Interrupt Safe Ring Buffer Library

October 25th, 2008

Christoper looks through a circular tube

I created a ring buffer library for embedded systems in C some years ago and have been using it when I need to add a simple queue to my software.  I knew it worked correctly since I created unit tests to validate the code.  However, I noticed that it wasn’t interrupt safe since one of the consumer variables is shared by the producer (the count).  This library requires disabling interrupts when consuming.  Not what I wanted.

There are a number of difficulties when designing ring buffers, mostly dealing with efficiencies of code or data, or the struggle between consumers and producers.  My generic ringbuf library had used a single fill count, but the count had to be updated by the interrupt service routine (producer) and by the routine that retrieved the data (consumer).  I tried to use read and write offset indices, but that required that I always keep an element open since the you can’t tell if the ring is empty or full when the head and tail are the same.

Absolute indices appeared to be interrupt safe, although they require that the buffer length be a power of two.  That seemed to be flexible enough for most embedded work.  I modified and tested my ring buffer library using that method, but my ringbuf, which allowed for a fixed length element,  seemed to be overkill for what I was using it for – gathering bytes from a serial interrupt service routine.  Its API also had a slight flaw such that if the consumer retrieved the data (via Pop rather than just viewing the first element), the producer was free to put new data into the buffer, overwriting the data just retrieved.

I had started my ring buffer library as a simple character (one byte) FIFO – first in, first out.  So, I revisited that code, and modified it to use absolute indices.  A simple byte ring buffer, first in, first out.  Now I had interrupt safe code that would work in my serial interrupt service routine.

Why go to the trouble to make a library module to handle a ring buffer when slapping the following quick and dirty ring buffer code (from Stefan) into the serial module would have worked as well?

   #define N 128
   volatile unsigned int head, tail;
   volatile char buffer[N];
   unsigned int inuse() { return head - tail; }
   void put(char c) { if (inuse() != N) { buffer[head++%N] = c; } }
   void get(char* c) { if (inuse() != 0) { *c = buffer[tail++%N]; } }

Because I needed to know that it worked correctly, and I like reusable library modules.  Especially high quality reusable modules.  Especially high quality reusable modules that include unit tests to validate functionality.  Unit tests that also serve as guides for implementers.

The new module files are ringbuf.c and ringbuf.h for the ring buffer with fixed sized elements, and fifo.c and fifo.h for the ring buffer with byte sized elements. All my versions of the ring buffer and the unit testing framework can be found in the ringbuf.zip file.

BACnet – First to the Moon, and Beyond!

September 16th, 2008

I drove to the BACnet meetings in nearby Atlanta and Bill photographed my license plate.  We need lofty goals, don’t we?

Convert to MP3 Konqueror Service Menu

August 5th, 2008

I wanted an easy way to convert music to MP3 from various formats under Konqueror in KDE on Kubuntu Linux.  I found an interesting post about creating a KDE Service Menu which got me started in the right direction.  However, I didn’t like the way ffmpeg converted to 64kbps MP3 quality and the bad sounding results regardless of the bitrate settings that I chose.  I tried lame, and was quite pleased with the results.  I also didn’t like the way the service menu used the entire filename without stripping the dotted extension, so I copied another service menu perl example.  My “Convert to MP3″ service menu script goes into the following location:

/usr/share/apps/konqueror/servicemenus/

File convertmp3.desktop:

[Desktop Entry]
ServiceTypes=audio/*
Actions=convertToMP3

[Desktop Action convertToMP3]
Name=Convert to MP3
Exec=lame -V2 %f "`echo %f | perl -pe 's/\.[^.]+$//'`.mp3"

Enjoy!

Gmail IMAP Invalid Credentials in Thunderbird

July 17th, 2008

I kept getting “Invalid Credentials” in Thunderbird when connected to my Gmail IMAP account.  I found the solution to be:

https://www.google.com/accounts/UnlockCaptcha?