All posts by Stuart Taylor

Ferrograph – secrets of the <SDX>

I haven’t played about with the Ferrograph LED displays for a while. Its one of those things, once the system is up and running, you don’t touch it. You change the system, that sends the content.

Recently i have received a number of emails from people who are trying to make something, anything appear on the sign. They google and end up at my old post about the Ferrograph signs/. In that post i mention that the phrase <SDX> needs to be sent at the start of a message, and it’s this particular aspect that is a little confusing.

Before we get into the meat, we need to make sure we are talking to the sign at the right baud rate etc.

Many Ferrograph signs come wired for RS422, read the old post to see how to wire it up for RS232 operation.

The SDX firmware can be configured to operate at different baud rates. The sign always operates at 8 data, no parity and 1 stop bit (8n1). The default baud rate with switches 5 and 6 off is 19200 baud, and other baud rates can be set as follows:

Switch 6

Switch 5

Baud Rate














Note that the 38400 baud rate is only available if the CPU is running at double speed, either due to fixed hardware speed, or a Z8S180 CPU being detected.

If (most likely) the sign is operating at single speed, this baud rate will not be available.

The bottom four DIP switches select the network address, in the range 00H to 0FH. This is not an ethernet address. Its for when multiple signs are daisy chained over RS422.

Address 00H is reserved as a broadcast address, and if the display’s address is set to it, it will act on every message received regardless of the message address. Similarly, the display will act on any message containing the 00H broadcast address, regardless of its own address.

To make hello world appear on the display, we need to send a properly structured message or packet. This is common with all displays of this nature. The SDX packet requires the addition of an “SDX” text field as well as the SOT character and the ASCII Address field. Therefore, the basic packet structure is as follows:

SOT  01H

“SDX” Text Field

Address Field

Optional Control Sequences


Data Record(s)




<SOT> (01H): Start of Transmission character, must be sent at start of message.

<SDX> The “SDX” text field simply consists of the fixed string of three ASCII characters: ‘S’, ‘D’ and ‘X’. It is used to ensure that the SDX firmware will only operate with compatible driver software, and not the driver software designed for the original Ferrograph UDP firmware. Note that the “SDX” text field is only required at the start of the basic packet structure, and not for nested Message and Page sequences.

These are more complicated message structures and wont be covered here.

<ADDR> The Address Field consists of two ASCII HEX Digits (e.g. address “00” represented by two bytes 30H 30H).  The address must be in the Range “00” to “3F”. For a message to appear on the display, the address in the packet must match the address set via DIP switches on the rear panel, unless the DIP switches are set to address “00”, where any address will be accepted. Note, however, that these bytes must always be valid ASCII HEX digits.

<SEP> (1EH): The separator byte is always required before the data record containing free text, some control sequences and any nested Message sequences.

<EOT> (04H): End of Transmission character. This must always be sent at the end of a message.

Therefore, to make the string “hello world” appear on the sign, regardless of its address, we need to send:

<01H><SDX><30H30H><1EH><hello world><40H>

To the display. Note, you don’t send the <> characters! I have simply used them to show how a message sequence is structured.

Within linux you should be able to:

echo -e '\01SDX\30\30\1Ehello world\40' > /dev/ttyS0

Or from windows:

you can use copy con and place the message structure in a file. I wont go into the how here, thats a subject for entire blog post, let me google that for you

Spider, Crawlers and Bots oh my!

A collection of crawlies…

User-Agent: robot
User-Agent: adidxbot/2.0 (+
User-Agent: AdsBot-Google (+
User-Agent: AdsBot-Google-Mobile (+ Mozilla (iPhone; U; CPU iPhone OS 3 0 like Mac OS X) AppleWebKit (KHTML, like Gecko) Mobile Safari
User-Agent: bitlybot
User-Agent: BOT/0.1 (BOT for JCE)
User-Agent: ClickTale bot
User-Agent: ContextAd Bot 1.0
User-Agent: DoCoMo/2.0 N905i(c100;TB;W24H16) (compatible; Googlebot-Mobile/2.1; +
User-Agent: Flamingo_SearchEngine (+
User-Agent: Fve Nutch Spider/Nutch-1.7
User-Agent: Googlebot/2.1 (+
User-Agent: Halebot (Mozilla/5.0 compatible; Halebot/2.1; <<
User-Agent: Mozilla/5.0 (compatible; aiHitBot/2.8; +
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; )
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.2)
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0 ; Claritybot)
User-Agent: Mozilla/5.0 (compatible; AhrefsBot/5.0; +
User-Agent: Mozilla/5.0 (compatible; archive.org_bot +
User-Agent: Mozilla/5.0 (compatible; Baiduspider/2.0; +
User-Agent: Mozilla/5.0 (compatible; bingbot/2.0; +
User-Agent: Mozilla/5.0 (compatible; BLEXBot/1.0; +
User-Agent: Mozilla/5.0 (compatible; EasouSpider; +
User-Agent: Mozilla/5.0 (compatible; Exabot/3.0 (BiggerBetter); +
User-Agent: Mozilla/5.0 (compatible; Exabot/3.0; +
User-Agent: Mozilla/5.0 (compatible; Ezooms/1.0;
User-Agent: Mozilla/5.0 (compatible; Genieo/1.0
User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +
User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Exabot-Thumbnails)
User-Agent: Mozilla/5.0 (compatible; linkCheck)
User-Agent: Mozilla/5.0 (compatible; LinkChecker/8.3; +
User-Agent: Mozilla/5.0 (compatible; linkdexbot/2.0; +
User-Agent: Mozilla/5.0 (compatible; Linux x86_64; Mail.RU_Bot/2.0; +
User-Agent: Mozilla/5.0 (compatible; MJ12bot/v1.4.4;
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Selenium Bot)
User-Agent: Mozilla/5.0 (compatible; proximic; +
User-Agent: Mozilla/5.0 (compatible; SEOkicks-Robot; +
User-Agent: Mozilla/5.0 (compatible; SemrushBot/0.97; +
User-Agent: Mozilla/5.0 (compatible; special_archiver/3.1.1 +
User-Agent: Mozilla/5.0 (compatible; TweetmemeBot/3.0; +
User-Agent: Mozilla/5.0 (compatible; URLAppendBot/1.0; +
User-Agent: Mozilla/5.0+(compatible; UptimeRobot/2.0;
User-Agent: Mozilla/5.0 (compatible; Yahoo! Slurp;
User-Agent: Mozilla/5.0 (compatible; YandexBot/3.0; +
User-Agent: Mozilla/5.0 (compatible; YandexImages/3.0; +
User-Agent: Mozilla/5.0 (compatible; YoudaoBot/1.0;; )
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot-Mobile/2.1; +
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729; Diffbot/0.1; +
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1) VoilaBot BETA 1.2 (
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; ) Firefox/; 360Spider
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv: Gecko/20101203 Firefox/3.6.13 << seen from this ip
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; Google Web Preview) Chrome/27.0.1453 Safari/537.36
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv: Gecko/20111107 Ubuntu/10.04 (lucid) Firefox/3.6.24 Mozilla/3.5 (Google-HotelAdsVerifier)
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Exabot-Thumbnails)
User-Agent: Mozilla/5.0 (compatible; MojeekBot/0.6;
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Selenium Bot)
User-Agent: Mozilla/5.0+(compatible;+PiplBot;++
User-Agent: Mozilla/5.0+(compatible; UptimeRobot/2.0;
User-Agent: msnbot/2.0b (+
User-Agent: msnbot-media/1.1 (+
User-Agent: msnbot-UDiscovery/2.0b (+
User-Agent: Pingdom.com_bot_version_1.4_(
User-Agent: psbot/0.1 (+
User-Agent: psbot-image (+
User-Agent: QuerySeekerSpider ( )
User-Agent: rogerbot/1.0 (,
User-Agent: SAMSUNG-SGH-E250/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/ (GUI) MMP/2.0 (compatible; Googlebot-Mobile/2.1; +
User-Agent: ShowyouBot (
User-Agent: SMNutchSpider/Nutch-1.7
User-Agent: Sogou web spider/4.0(+
User-agent: spider
User-Agent: Twitterbot/1.0
User-Agent: WeSEE:Search/0.1 (Alpha,
User-Agent: WeSEE:Search/0.1 (Alpha,
User-Agent: WIRE/0.22 (Linux; x86_64; Bot,Robot,Spider,Crawler)
User-Agent: Yahoo:LinkExpander:Slingstone
User-Agent: Yeti/1.0 (NHN Corp.;

Thought of the day.

Conway’s law is an adage named after computer programmer Melvin Conway, who introduced us to the idea back in 1968, yes they had computers back then kids. It states that:
“organisations which design systems … are constrained to produce designs which are copies of the communication structures of these organisations”.

What do we do about it?

DevOps. While devops is a portmanteau of development and operations, it is not another team. The last thing our IT family needs is yet another functional silo.

DevOps is a set of protocols and practice’s that stresses the importance of communication, collaboration and integration between the software development teams and the rest of our information technology professionals.

We need to start thinking beyond our IDE, we need to start thinking beyond our kanban boards and our service management systems, we need to increase our collaboration and our communication, and we need to make sure that we never create a monster like shared dependency again.

call yourself a software tester?

I have just been prompted (via some AdWords) to write a quick blog post around the subject of defect prevention. Not detection, prevention.

For a long time the software testing community has been taught that unless a defect is being managed in a defect management tool, then whatever testing process you are following is probably not fit for purpose. That is, you cant be doing serious software testing, because you are not being serious about your bugs. But it that true?…

Continue reading

Adafruit I2C RGB 16×2 LCD+Keypad & Raspberry PI

I recently bought one of these

Adafruit RGB Negative 16×2 LCD+Keypad Kit for Raspberry Pi from an Adafruit reseller in the UK (via eBay), for two reasons. 1 to use in my OBDII project, and 2 to learn how they did it (serial to parallel and some 4 bit mangle).

You see the device uses an MCP23017 16bit I2C port extender, and most 16×2 LCD displays require a 4-bit bus (4 data lines) , and an RS, RW and E lines, so i was interested to see how Adafruit were implementing the lcd display protocol over the i2c bus….

Continue reading

The wrong type of glue?

I kept on hearing the same kinds of grumbles on the floor and in retrospectives. The team were basicaly saying, we are being forced to use the wrong type of glue. The team are a pasinate lot, and so full and frank debates would flourish on which was the best type of glue, and who knew how best to apply it.

a selection of glues
Which glue is best for Baths?

Because i’d heard these grumbles a few times, i started to wonder why my awesome team were still struggling over what seemed trivial to me, just choose one and try it, right?

That is until it dawned on me.  What on earth are they trying to glue back together?

The bath, as it turns out.

The problem with gluing the bath was explained to me in great detail, some glues would leave an ugly stain, while others were very messy to handle, some other types of glue would set before the bath was stuck together again, and in most cases the glue wasnt water proof and the bath would leak. Despite this, the team were determined to get this right, they would get the bath glued together!

a bath in two halves
How to best stick the bath back together again?

Why is the bath in two halves? Seems like an obvious question now, but somehow i hadn’t asked that of the team.

“We cut the bath in half because it didn’t fit, someone ordered the wrong size bath” came the reply. So focused on delivery, the team hadnt stopped to think about telling the customer the batch was the wrong size, they just reached for the saw and cut it in half.

Obviously we haven’t stopped writing code, and invested in plumbing, i’m using a metaphor that describes what we have been doing for the last couple of months really well. In fact i can extend it a little further.

When i asked one of the dev team leads why they cut the bath in half, they suggested that they had been told to do so, but had they misunderstood what was being said?

When they had told foggy, the tech lead that they had an issue with the bath, he focused in so tightly on the problem that he only suggested that their plumbing was very complicated and that complexity was storing up technical debt that would be hard to pay down later, began to show them how they should improve and simplify it, he missed the fact that the bath was in two completely. They took his ignorance of the matter as acceptance of the fact.

To compound matters further, when JRH one of the BAs, thought he was being pragmatic in his approach, the developers actually took what he was saying as, stop crying about the glue and just do it. It turns out the BA didnt know the bath was in two either. He had made the same assumption as me, what’s so hard about choosing a glue?

How did this happen? I’m not entirly sure, but i have identified several problems that have grown like mould on a loaf of bread, slow and sure until it becomes unpalatable.

The good news is that the team obviously want to work and want to deliver, so eager to do so, that they made a decision that would allow them to continue to work. In doing so they unwittingly slipped down the rabbit hole.

In my next post i’ll explain how we are dealing with the fat end of the Business Requirement funnel, and this is causing the team to thrash.