October 30, 2012

300 dpi

Twenty years ago, I bought my very first laser printer, the HP LaserJet IIIp. It had amazingly sharp printout compared to typical printers of the day, and it was 300 dpi. Today, we have 300 dpi on a tablet computer. I wonder what we'll see in another twenty years?

August 6, 2012

Arduino RFID (part 3)

(... continued from part 2)

I'm famous!

When I presented my new standalone RFID box to HR and management, their only reaction was... why is there no beep when a card was scanned?

Right. I know that audio feedback is one of the easiest and simpliest forms of physical feedback, and I should know that management wouldn't care about little technical details like being able to access logged data over http. Hmmf. Anyway, I managed to find a $1 piezo buffer for some hi-fi beeping.

Final BOM of my little RFID box:

Arduino Mega (clone)
Stronglink SL018 Mifare module
Ethernet Shield with POE
16x2 character LCD display
DS3232 RTC module
Generic piezo buzzer
Generic plastic project box

All parts were purchased locally from ETT (Arduino, LCD, DS3232) and ThaiEasyElec (SL018 and Ethernet Shield).

Standard Arduino libraries used to support the hardware include SPI.h, Wire.h, LiquidCrystal.h, Ethernet.h, EthernetUdp.h, EEPROM.h, and wdt.h. External libraries include SL018.h, Time.h, DS1307RTC.h, and SdFat.h. The Arduino Mega uses the Optiboot loader with working watchdog timer. Due to all the libraries and strings, the compiled sketch is around 45K, so it will not work with the smaller Arduinos.

I'm still not sure if making my own RFID box is a good idea. However, the completed RFID box has far more features than any commercial RFID readers available locally (not counting eye candy like color touchscreen LCD display and talking clock), and costs a fraction of the price even though I'm putting the full Arduino board inside. I'm just not sure about the longevity of the individual parts or my soldering skills. But then again, the old RFID reader we had that died with the flood had frequent failures and the clock was never accurate. The 125 KHz prox cards used with that system was prone to failure too. Plus, I've opened up the reader and it was a rat's nest of wires.

I've been really busy lately with family matters. But I will post the source code of my RFID box in the next and final installment of this series.

(... continued in part 4.)

July 28, 2012

SysAdminDay 2012


I imagine most sysadmins are lazy like myself, that's why we make great sysadmins: we make scripts and automate things to make life easier for ourselves. We also like tools, especially multi-tools. Three years ago I bought myself a Leatherman Skeletool CX that I still use almost daily. This year I bought myself a Sea to Summit spork.

Unfortunately, I didn't take the rest of the day of cause I was still stuck in non-stop meetings.

July 1, 2012

Saving lives

My mom passed away from metastatic breast cancer to the lungs two weeks ago. Near the end, she had a lot of difficulty breathing, and I was at the hospital day and night to take care of her for the last few weeks.

When she was awake, I would talk with her or help her eat or wash. While she rested, I would roam the hospital and chat with the nurses. After a few days, the nurses finally noticed that no matter what shift they're in, I was always awake and around.

"How is it that every time I'm taking a shift, you seem to be awake?"

"I'm an IT guy, and I fix computers. I'm always on a 24-hour standby, and before I became a manager, I used to work around the clock all the time. My job is actually a lot like yours."

"Eh? We save human lives, you fix machines."

"We save machines and data. Machines can be repaired or bought new, data are often irrecoverably lost."

The nurses still weren't convinced, "Yeah, but when we lose a patient, we lose a human life."

"True, but think about this. Dying is a natural process of life. When you lose a patient, the family grieves for the dead, they might even blame you or sue you for the loss. But as time passes, they accept the loss, recover, and then go on living. It is a fact that no one lives forever.

"For us computer guys, losing data is permanent. A manager accidentally deleted a file that he took days to make on the night before his big presentation to his bosses, and he came to us to bring back the file. How do you bring back the dead? He then went to his bosses to blame us for the loss. And each time he encounters a new problem, he remembers all his past problems, and the past never goes away. Essentially, my users never recover from their losses, and every loss is cumulative.

"My job is thankless like yours. Do you get thanked for lives saved? Me neither. No thanks, and always blames."

"..."

"Thank you for taking care of my mom. You guys are the best."

April 1, 2012

Arduino RFID (part 2)

(... continued from part 1)

Just because the HR people loved something doesn't mean the management loved it. When the HR guys presented the Arduino RFID scanner connected to a PC with huge LCD TV's that displays employee photos to the management, the management people immediately asked, who watches the photos, and who watches the watchers?

Okay... back to the drawing board. I had previously hooked up my 16x2 character LCD display as a backup display in case the TV's blow up, I decided to take the idea further. I also decided since we're no longer going to use large LCD TV's, there's no point in hooking up a computer any more, and perhaps I could make the whole thing self-contained...

More importantly, being self-contained means I need connectivity directly from the Arduino, so I added an Ethernet Shield to the setup. The Ethernet Shield has a MicroSD slot that could be used to log data. In order to more clearly show whose card was scanned, I decided to not use the Mifare card's UID, but instead will write the employee name into the card. This way, the employee can see her name shown on the LCD display when she clocks in or out.

Of course, going standalone also means I need RTC and/or NTP. Using NTP seemed to be problematic at first (appears to be fixed in Arduino 1.0.1), and I also wanted my RFID box to be completely standalone, so I added a DS3232 module. The DS3232 would normally keep very accurate time, but a nightly housekeeping function would sync it with NTP if the NTP time is sufficiently similar to the RTC time. The housekeeping function also renews the DHCP lease.

When a card is successfully scanned, the current date and time, the card's UID, and the employee data stored on the card are saved to the MicroSD card. The employee data is then shown on the LCD display. The data is logged on the MicroSD card as plain text files, grouped into year directories and each day is separated into a single file. e.g. entries logged on April 1, 2012 would be saved in /2012/20120401.csv

Entries can be read off the MicroSD card by opening a web browser and going to http://[ip]/20120401 and the CSV file would be displayed in the web browser. I used the cheapest 4GB MicroSD card I could find, and by my calculation, it has enough storage for around 200 years or the Rapture, whichever comes first.

Special admin cards can be created by writing a special employee code to the card. When this card is scanned, pre-determined actions can be performed. In my case, I use the special cards to switch the RFID box from clock-in to clock-out and vice versa. Clock-in/out status are also shown on the LCD display in Thai by using custom characters, and the status is also stored into EEPROM. Because the 16x2 LCD has limited space, I chose to show the day of the week, the current time, and clock-in/out status on the top row. When a card is scanned, the employee name is shown on the bottom row.

After implementing the admin card function, I also added the clock-in/out status as well as the MAC address of the RFID box into the log. This is because we will actually have more than one reader, and it's necessary to differentiate whether the employee is clocking in or out, and at which reader.

In order to write employee data to the Mifare cards, I added some code to make the RFID box as a writer too. I haven't written a nice custom interface for Windows yet, so I'm only using a terminal program. Sending 'a' to the Arduino puts the RFID box into admin mode which allows initializing new Mifare cards and writing, reading, or deleting employee data from the Mifare cards.

(Continued in part 3...)

March 12, 2012

Arduino RFID (part 1)



This Arduino thing is addicting. Recently, we were looking for a new employee time attendance system (the old one went away with the flood) and since almost everything available locally is either garbage or overpriced (often both), I decided we should roll our own.

I've heard of the Stronglink SL018 while reading about Arduino libraries. The SL018 is a Mifare reader/writer module that uses I2C. It's available locally for cheap and someone had already written an Arduino library for it. The library had not been updated for 1.0 but I updated it by simply changing a few lines.

After hooking the SL018 module to my Arduino, I wrote a little sketch to send the Mifare card's UID to the connected computer over serial port. On the very first try, I discovered I could scan two cards simultaneously by holding the two cards slightly apart, as if holding playing cards. That's not very good for an employee attendance system. Fortunately, the SL018 has a TagSta[tus] pin that simply outputs LOW if a card is present, so I modified the sketch a little bit to ignore further readings unless the TagSta pin has been reset by removing the card.

The SL018 module also has a red user controllable LED, so I modified the sketch a bit more to make the LED light up if the same card is scanned for the second time without sending the data over the serial port. (This is because we have technophobic employees who don't trust anything electronic, and will stand in front of the reader and scan their cards hundreds of times, just to make sure the data is actually stored. I'm not making this up.)

On the computer end, I wrote a little demo program to receive the UID from the serial port, play a wav file, display a jpg image ("employee photo") using the UID as the filename, and record the UID along with the timestamp. I suggested that we could use large LCD TV's instead of a computer to display the employe photos, and the HR people loved the whole setup and idea.

(Continued in part 2...)

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.

Edit: I noticed that the Optiboot repository actually contains a special boards.txt for Optiboot. However, the entry for Arduino Mega isn't quite correct, but it does contain a different maximum_size value. This is what I eventually put into my boards.txt.

megao.name=Arduino Mega Optiboot
megao.upload.protocol=arduino
megao.upload.maximum_size=130048
megao.upload.speed=115200
megao.bootloader.low_fuses=0xff
megao.bootloader.high_fuses=0xda
megao.bootloader.extended_fuses=0xf5
megao.bootloader.path=optiboot
megao.bootloader.file=optiboot_atmega1280.hex
megao.bootloader.unlock_bits=0x3F
megao.bootloader.lock_bits=0x0F
megao.build.mcu=atmega1280
megao.build.f_cpu=16000000L
megao.build.core=arduino
megao.build.variant=mega

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.