February 28, 2012

Arduino Uno serial port

I finally bought an "original" Arduino Uno. It costs far more than the Arduino Mega local clone that I've been using, but the main reason is because I want to see how the ATmega16U2's COM port emulation works in Windows. (I have the Uno R3, older revisions of the Uno has the ATmega8U2.) Of course, I want to support the Arduino project.

Older Arduino's and most of the Arduino clones use the FTDI FT232R chip for the USB UART. FT232R works great with Windows, and has the ability to change COM ports, which is really important for supporting older programs that have fixed COM ports. In fact, after discovering how good the FT232R works from using my Arduino Mega clone, I started buying USB to RS232 adapters that use this chipset, and they work with everything I've thrown at them, including DOS applications running in Windows.

One feature the FT232R chip has is that if the COM port is fixed to a particular adapter or Arduino board, Windows will remember the setting and it will continue to be that COM port, unless manually changed. This is important if I have multiple serial port devices all connected to the same computer. They all remember what COM ports they're supposed to be, and everything just works.

You might think this is the standard USB behavior for Windows, but NOOOOOOOO. Recently we got some industrial barcode printers from Argox. While they're decent barcode printers, whoever designed the idiotic USB interface needs to have infinite barcode printers stuffed up their behinds. The problem is that every single Argox printer looks like the same printer to Windows. So whichever printer I turn on first is always "Printer 1". This might be fine for people with just one printer, but I need to have multiple different sized labels printed simultaneously. So my users have to remember to always turn on their printers in a particular order.


Anyway, I discovered both the FTDI driver and the standard Windows driver lets you change the COM ports without any limitation. But the FTDI has an additional option that's really useful: the ability to disable the serial port enumerator. The serial port enumerator is a left-over thing from when mice were plugged into the serial port. If Windows sees incoming data over the serial port when booting up or configuring hardware devices, it will automatically configure the serial port device as a mouse. This is problematic if you have an Arduino or other serial port device connected, and your mouse pointer goes crazy, this is what's happening.


Unfortunately, Arduino Uno's ATmega16U2 emulates a standard COM port so perfectly, it still uses Windows' own driver. Fortunately, the ability to change the COM port number is still there, but sadly there's no built-in way to disable the serial port enumerator.

Before Windows 7, Microsoft had a COMDisable Tool that does the job. With Windows 7, it looks like you're outta luck. Either go back to Windows XP, or use an FTDI based adapter with the serial port enumerator disabling option. But wait, what about the Arduino Uno? Well, don't let it send data over the serial port in a mouse-like manner, and all should be fine.

... Speaking of serial port mouse. You think Apple invented shiny white products? Nope, Microsoft did with the 9-pin serial mouse, also known as the soap mouse at the time. It was shiny and white, and five minutes after you start using it it's covered with fingerprints and scratches, and people loved it. I had one and I hated it.

Image courtesy: The MCA Mafia

February 22, 2012

Arduino Mega Optiboot

I wrote a little sketch on my Arduino Mega clone coupled with an Ethernet Shield clone to reboot my remote desktop servers in case they lockup. The question is, what monitors the monitor? Of course, being a microcontroller, I figured the AVR surely must have some kind of watchdog function to reboot itself.

Unfortunately, the watchdog function didn't seem to work correctly. I simulated lockup conditions by using a long delay(). The watchdog happily triggered a reboot, but then the Mega gets into some kind of infinite reboot loop that could only be exited by uploading another sketch. (Just pressing reset or power recycle didn't work.) Upon further research, I discovered the watchdog doesn't function correctly on the Arduino Mega. The fix apparently is either to use Optiboot, or use a bootloader that has this bug fixed.

Optiboot comes by default for the Arduino Uno, and is actually available for the Arduino Mega, it's just not distributed in the Arduino IDE by default. I could either compile it by myself, or download it from the Optiboot repository. I would need to use an AVR programmer to flash the bootloader. Fortunately, my Arduino clone, the ET-EASY MEGA1280 is self-programmable by setting onboard jumpers.

So I flashed the Optiboot bootloader onto my Arduino Mega. But after the flashing was completed I discovered I could no longer upload sketches to it. It didn't feel completely "bricked" though, as I could re-flash the regular bootloader back to it and it worked again, but with Optiboot loaded, it didn't accept sketches any more. It kept giving me this error: sync avrdude: stk500_getsync(): not in sync: resp=0x00

It occured to me that because the board now contains Optiboot, I should be uploading at 115,200 kbps, and I should probably choose Uno as the board type. This is similar to how older boards such as the Arduino Duemilanove, when upgraded with Optiboot, effectively become the Uno and should be treated as an Uno in the Arduino IDE.

So I tried choosing Arduino Uno from the board type menu. It now complained that I don't actually have an Arduino Uno or a board based on the ATmega328P. The exact error was: avrdude: Expected signature for ATMEGA328P is 1E 95 0F  Double check chip, or use -F to override this check. I probably shouldn't override the check, since my ATmega1280 chip has much larger flash space, so I should probably just edit boards.txt instead.

Modifying the Arduino Mega section in boards.txt and changing the mega.upload.speed to 115200 fixed the upload problem. Even though Optiboot takes less space, I didn't modify the mega.upload.maximum_size value since I had no idea how much flash space Optiboot saved and what the maximum value should be, and 128K is enough for everyone. But since I have both regular Arduino Mega and Mega with the Optiboot, I decided to create a new section called Arduino Mega Uno.

The only issue I have with Optiboot is that once in a while, after upoading sketches or after plugging in the USB cable for USB power, the board doesn't start itself correctly. I need to push the reset button to run the sketch. The problem seems to be related to the serial port, since if I disable auto-reset (I have a jumper for that too.) it always works correctly. It also always starts correctly if I power up using an external power supply. Strangely enough, it seems to always start correctly too if I have shields installed, but I haven't tested this completely.

And yes, after installing Optiboot, watchdog works correctly now.

January 5, 2012

Red Friday

I never knew there's such a thing as Red Friday as opposed to Black Friday. But here it is.


Most things are roughly 10% off, equivalent to the Black Friday sale in countries that celebrate Thanksgiving.

January 4, 2012

Fixing lock up on SerialPort.Close()


Earlier this year I bought several Arduino boards to do some hardware interfacing and programming. It all worked out pretty well excep the part where the application locks up completely.

The Arduino connects to the computer using USB, but it emulates a serial port, it's really easy to communicate with the Arduino using the standard SerialPort Class in Visual Basic 2008, but the application sometimes locks up when I'm done using the serial port and attempt to close it. A Google search reveals hundreds of other people facing the same issue, and apparently no easy solution. So after some head banging, I found that the trick was to put the SerialPort.Close() method into a thread, and also handle the I/O exception that sometimes happens. See below for code.

Instead of just closing the port, I created a thread:
Dim t As New Thread(AddressOf ClosePort)
t.Start()
And put the actual Close() method into a subroutine:

Public Sub ClosePort ()
SerialPort1.Close()
End Sub

In the subroutine that handles DataReceived events, I added an exception handler:
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs)
    On Error Resume Next
    Me.Invoke(New myDelegate(AddressOf updateTextBox), New Object() {})
End Sub
In this example, the subroutine invokes the updateTextBox subroutine, which does a ReadLine on the serial port and sends the captured data to a textbox.

It's obvious by now that because SerialPort.Close() sometimes waits on DataReceived and the UI, so just closing the port when that occurs hangs the application. By putting SerialPort.Close() into a new thread, instead of the application hanging, the DataReceived event started giving exceptions due to the port being closed, so handling the exception fixed that issue. At first I tried removing the event handler, but that only reduced the frequency of the exceptions, but did not completely get rid of it. Using an exception handler was probably best, but also see disclaimer below.

Disclaimer: I'm not a programmer, and this may not be the best way or even the right way to solve the serial port lock up issue, but it works for me.

December 26, 2011

WRT54GL vs. H2O


This is the PCB of a good old Linksys WRT54GL that was completely submerged for approximately one month during the Great Thailand Flood of 2011. Oh, the router was actually placed on a desk, the water level was much much higher than that.

My domain and database servers were all safe since they were on the second floor, but I had to evacuate them (by boat) to another site, which I'll write in detail the next time. Computers that were on the ground floor were all dead, either directly by water or rusted by the humidity. Some I could actually salvage the hard drives or CPU's since the water level was lower, others were completely underwater.

October 24, 2011

Server evacuation

I'm stuck in the middle of the Great Thailand Flood of 2011. My entire factory was flooded, and I had to evacuate my server backups to a safe and dry place.

A few years ago, when I was writing policies for SOX compliance, there was a section about risk assessment and business continuity planning, and one of the issues was how to resume operations in case of fire or flood or other acts of God. Who would've thunk that after less than four years, everything I wrote has to be put into actual usage?

So, we were evacuated out to a nearby hotel with free Wi-Fi, and all the managers are connected to the free Wi-Fi, and then they need printing. So I went back to the flooded factory and took out (by boat) a trusty Linksys WRT160NL and a Canon inkjet printer. Previously I talked about using the WRT160NL to share USB printers, but this is slightly different since I don't actually have a LAN any more.

It turned out to be quite easy, I just joined the WRT160NL to the hotel's free Wi-Fi by using client bridge, then used Angry IP Scanner to find a free IP address outside of what I think is the normal DHCP range, and then I just pointed everyone's printer to the new IP address of the WRT160NL, and then we got printing.


While setting things up, I suddenly lost Wi-Fi connectivity, and I called the hotel's front desk to ask them to reset the Wi-Fi, and they told me the only Wi-Fi they have is down at the lobby, and it was working perfectly. I ended up having to find a maid on my floor to ask her if she has ever seen a little box with blinking lights, and she pointed me to a Linksys WAP54G. I simply power cycled the access point and all was fine again.