listComPorts – Windows command-line tool for USB-to-serial

Did you know each Arduino has a unique serial number in its USB interface that you can use to distinguish one Arduino from another? If you deal with multiple Arduinos, knowing exactly which one is plugged into your computer can be a real time-saver. But actually getting at this serial number and mapping it to COM ports can be challenging.

For Windows computers, here’s “listComPorts”, implemented both in GCC C code and in VBScript, both available from my usbSearch github repository.

It gives the COM port number, the manufacturer name, the USB Vendor ID and Product ID (VID & PID) and the serial number. The result is a concatenation of the VID, PID, and serial number that Windows calls a “PnPDeviceID”. You can use the whole thing, or pick off the parts you need using simple string processing libraries. In the example above, the Arduino Diecimila has a VID/PID pair of 0403/6001 and the Teensy has a VID/PID of 16C0/0483.

Arduino Serial Numbers

In the above example, the Arduino Diecimila (which has an FTDI chip) has the serial number with a “+”-sign after the PID. So, the serial number is “A6004CCF”. The Teensy can have a programmable serial number and by default it’s set to “12345”.

With Arduino UNOs and future Arduinos, the Arduino team has their own VID/PID pair, which let’s them assign different PIDs for different classes of Arduinos. The UNO also has a much longer unique serial number than older Arduinos using the FTDI chip.

Here’s an example with two Arduino UNOs:

The serial numbers are separated by the VID/PID pair with a backslash. So my two UNOs have the serial numbers “64936333936351408161” and “6493234373835191F1F1”. Using this info, I can be sure exactly which Arduino I’m dealing with.

How it works

The C and the VBS versions both utilize the WMI infrastructure that’s been around since Windows 2000 to query the machine about its configured PnP devices. The WMI is a huge data structure of just about any information in Windows. Except, it seems, good information about COM ports. While there is a “Win32_SerialPort” table in WMI, that only contains information about hardware serial ports, not USB-to-serial adapters. Instead, these two tools look at the “Win32_PnPEntity” table. While this table does list USB-to-serial adapters, it does not contain a proper mapping of the adapter’s USB or PnP ID to COM port. Instead, these tools do a string search on the “Caption” field for the string “(COMn)” where “n” is a number. It’s an incredible hack but seems to work.

Other operating systems

On Mac OS X and pre-UNO Arduinos, knowing exactly which Arduino you were dealing with was easy because the FTDI driver put its serial number as part of the name of the serial port. For example, the port name created by the FTDI driver was “/dev/tty.usbserial-A6004ccf” and the serial number was “A6004ccf”.

With the UNO, the Arduino team used a reprogrammable ATmega8/16u USB chip using standard CDC USB-to-serial interface, which all OSes support natively. Unfortunately, on Mac OS X, the OS’s CDC driver creates a serial port for the UNO based on USB port location, not Arduino serial number.

Thus where you plug in the UNO into determines its serial port name. For instance, on my Mac, plugging in an UNO with serial number “64936333936351408161” gives a serial port with the name of either “/dev/tty.usbmodemfd131” or “/dev/tty.usbmodemfa141” depending on which USB jack is used. Even if you plug in a different UNO in the same jack, you’ll get the same serial port name. This is useful for some applications, but not if you need to know exactly which UNO you’re dealing with.

For Mac OS X, I use a tool I wrote called listArduinos.pl. It tries to determine the serial port names of every Arduino Uno. It’s out looks like:

bokbok% ./listArduinos.pl         
Finding Arduino UNOs...
/dev/tty.usbmodemfd131 - 0x2341/0x0001 - 6493234373835191F1F1
/dev/tty.usbmodemfa141 - 0x2341/0x0001 - 64936333936351400000
Found 2 Arduino UNOs
bokbok% 

From Illustrator to Eagle: Vector graphics in circuits


Eagle is a great cross-platform, free-for-non-commercial-use tool for many of us designing our own circuit boards. But it has a pretty glaring omission: the ability to import vector artwork to use as board outlines, logos, etc. You can import bitmaps via the finicky “import_bmp.ulp” ULP add-on, but bitmaps can’t work for board outlines. So we struggle with Eagle’s rudimentary vector drawing tools or have boring rectangular or circular boards. I think I’ve found a way to robustly transfer vector artwork from Illustrator to Eagle. Below I show an “amoeba” vector shape in Illustrator being converted and used as a board outline in Eagle.

The short version of the steps are:
1. In Illustrator, add many extra anchor points
2. In Illustrator, export artwork as R13 DXF format
3. In Eagle, run the “import_dxf_polygons_v4.ulp” on the exported DXF file
4. Use resulting shape in your circuit

This is a fundamentally cross-platform technique: no special binaries needed, like some Windows-only DXF converters. Also, it should work for any other vector program that can export to a DXF format. And since the Eagle importer is public domain and freely inspectable, it can be improved over time. The importer is currently limited in many ways, but seems pretty usable, given appropriate input.

Step 1: Add Extra Anchor Points to Shape

The import command in Eagle produces only straight lines as output – any curves in your shape will be approximated by straight lines. To get around this, add extra anchor points/nodes to your shape. Add enough until you feel comfortable that the number of extra points sufficiently describes your shape. In Illustrator, this means running the “Add Anchor Points” repeatedly. You can find the command under the Object/Path menu:

Zoom into your shape when adding anchor points to see the points being added. Here’s a before-and-after of part of the amoeba shape:

If you don’t see the anchor points on your shape, be sure “Hide Edges” is turned off under the “View” menu.

Step 2: Export Shape as DXF

Illustrator supports exporting to DXF files natively. For importing into Eagle, we want the older R13 version of DXF. Here’s the settings I use in the DXF export dialog:

Be sure to place your shape as close to the lower left of the page in Illustrator, otherwise the shape will be far away from the origin in Eagle. (which is at the lower left)

Step 3: Import into Eagle

The DXF import is performed by the ULP “import_dxf_polygons_v4.ulp“. It is an updated version of the nice “import_dxf_polygons.ulp” extension written by Tim Ruetz and originally available from the Cadsoft Eagle userfiles misc area. I modified it slightly to let you select between WIRE (outline shape) and POLYGON (filled shape). Also, with WIRE, you can import unclosed objects, which you can’t do with POLYGON. Download the updated version here: “import_dxf_polygons_v4.ulp” and remember where you saved it.

In Eagle, from the Board window of your design, click the “ULP” button on the toolbar. Eagle will open up a “Run” file dialog. Navigate to where you downloaded the “import_dxf_polygons_v4.ulp” file and open it. You will be presented with a second file open dialog for “DXF file to import”. Navigate to your exported DXF file and open it. Then you’ll get the main import dialog:

From here you can rescale and mirror the shape if need be. The most important option is arguably the “Import to layer” one. For board outlines, use the settings:
– Layer: “Dimension”
– Type: WIRE
– Pen width: 0.0

When you click the “Execute” button, the shape will be placed into your board.

If you can’t see your shape, click the “Zoom Fit” button to fit all objects in the window. (the one to the right of the ULP button in the Zoom area of the toolbar) Now place your shape using a Group move.

Be careful using the POLYGON type. For shapes with interior holes, like the amoeba in this example, a POLYGON will fill in those holes, probably not what you want:

In most cases, use the WIRE type instead. It will also let you use open shapes like a spiral:

This isn’t useful for board outlines (which need to be closed), but could be useful for custom traces.

Let me know if you use this technique, or improve upon it. I think I’m going to try making this crazy little amoeba board that has an ATtiny on it, a bunch of LEDs, some I/O pins and a battery pack. :-)

(thanks to Carlyn for the inspiration and help in figuring this out, particularly in how to wrangle Illustrator)

NFC & RFID on Android, my Where2.0 2011 talk

I was invited to be a speaker at O’Reilly Where 2.0 Conference. It’s a conference mostly about mapping technologies, location-based services, and interesting new location-aware mobile apps.

I spoke about RFID and NFC, in the context of the release of the new NFC-capable Android phone, the Google Nexus S. Having an RFID reader in a phone could cause a big change in how we interact with the world around us. I talked about what RFID and NFC technologies are, how they work, some examples of them in the world and on Android, and how to add NFC capabilities to your Android app. And if the rumors of the new iPhone 5 are true, we’ll soon be awash in NFC applications.

My slides with notes: nfc_rfid_on_android_todekurt_where20.pdf (4.5MB PDF)

And here it is in slideshare:

WiFi for Arduino with Asus WL-520gu

I love Arduino but its lack of wireless bugs me. And it sucks that WiFi Shields for the Arduino cost as much a cell phone. I want something cheap. Turns out, small, cheap WiFi routers like the Asus WL-520gu can run the DD-WRT Linux firmware and act as serial-to-network gateway for Arduinos (or most any other USB device). Here’s how to do it.

(Hey, is this a Wifi-controlled BlinkM? I think it is.)

A quick video showing a router acting as a serial-to-network gateway:

This is not that new of a concept, hacking Linux onto a router for some neat DIY purpose. One of my favorite past hacks is MightyOhm’s WiFi Radio project. And of course, see my own book Hacking Roomba for an example of how to put a Roomba on the Net.

This post is specifically about trying to make a DD-WRT router a transparent gateway for an Arduino.

The steps are:

  1. Install DD-WRT Firmware
  2. Configure Router to be WiFi Client
  3. Do Some Tests
  4. Install USB Serial Drivers
  5. Install Serial-to-Network Proxy

Continue reading “WiFi for Arduino with Asus WL-520gu”

ReflashBlinkM: Update your BlinkM’s firmware

All BlinkM-family devices can have their firmware updated. This makes them great for tiny development boards for ATtiny processors. ReflashBlinkM is an application that makes it easy to put back the original firmware or update a BlinkM to the latest firmware.

Previously you needed an AVR ISP programmer like the AVRISPmkII or the USBtinyISP. Thanks to the ArduinoISP sketch that ships with Arduino, if you have already have an Arduino, you can easily reflash your BlinkM with new firmware.

The ReflashBlinkM application is a tool for Mac OS X and Windows that uses ArduinoISP to help you reflash BlinkMs to their default firmware.

This is what it looks like:

Here’s one way of hooking up a BlinkM to an ArduinoISP:

And here’s a video of a BlinkM MinM being reflashed:

For full instructions, see the ReflashBlinkM page in the blinkm-projects Google code site.

SoftI2CMaster: Add I2C to any Arduino pins

[update 20150128: changed links to SoftI2CMaster project on Github]

Ever wanted to use any pair of pins for I2C on Arduino, not just the dedicated pins on Analog 4 & 5? Me too, so I made a quick little Arduino library called “SoftI2CMaster”, available in the “blinkm-projects” Googlecode repository.

Get it here: SoftI2CMaster on github

It’s still a work in progress, but it can write data pretty successfully and do it over longer cables than normal.

For the VIMBY/Scion Hackerspace Challenge, I created an array of BlinkM MaxM-powered accent lights for the device we made. Because the I2C cable was longer than a few feet, the normal Wire library that BlinkM_funcs.h uses to communicate with BlinkMs couldn’t be used. This is because the Wire library assumes a perfect bus. If there is any noise or other bus problems, the Wire library will currently lock up. For the SoftI2CMaster library, I wanted it to be very tolerant, even lazy, about bus problems and also have more tunable timing to let you slow the bus down. Of course, you still need pull-up resistors on the two lines. I’ve found using 2.2k resistors to be good.

The SoftI2CMaster API follows Wire’s API pretty closely:

  • SoftI2CMaster(sdaPin,sclPin) — create an new SoftI2CMaster for the two pins specified
  • beginTransmission(address) — begin sending data
  • write(data) — send some data (byte or byte arrays)
  • endTransmission() — stop sending data

In use it looks something like this:

#include "SoftI2CMaster.h"
const byte sdaPin = 7;
const byte sclPin = 6;
SoftI2CMaster i2c = SoftI2CMaster( sdaPin,sclPin );

i2c.beginTransmission( 9 );  // write to address 9
i2c.write('c');
i2c.write(255);
i2c.write(0);
i2c.write(200);
i2c.endTransmission();

There is a simple demo for BlinkMs that this library currently lives in. It’s called “BlinkMSoftI2CDemo” and shows off a simplified BlinkM_funcs called “BlinkM_funcs_soft.h“. The entirely of BlinkMSoftI2CDemo is shown below.

const byte sdaPin = 7;  // digital pin 7 wired to 'd' on BlinkM
const byte sclPin = 6;  // digital pin 6 wired to 'c' on BlinkM

#include "SoftI2CMaster.h"
SoftI2CMaster i2c = SoftI2CMaster( sdaPin,sclPin );

// must define "i2c" before including BlinkM_funcs_soft.h
#include "BlinkM_funcs_soft.h"

byte blinkm_addr = 9;

//
void setup()
{
  Serial.begin( 19200 );
  Serial.println("BlinkMSoftI2CDemo");

  BlinkM_off(0);

  for( int i=0; i< 100; i++ ) {  // flash the blinkms
    BlinkM_setRGB( blinkm_addr, 255,255,255 );
    delay(10);
    BlinkM_setRGB( blinkm_addr, 0,0,0 );
    delay(10);
  }
}

void loop()
{
  byte r = random(255);
  byte g = random(255);
  byte b = random(255);
  
  BlinkM_setRGB( blinkm_addr, r,g,b );
  delay(10);
  BlinkM_fadeToRGB( blinkm_addr, 0,0,0 );
  delay(1000);
}

void BlinkM_off(byte addr)
{
  BlinkM_stopScript( addr );
  BlinkM_setFadeSpeed(addr,20);
  BlinkM_setRGB(addr, 0,0,0 );
}

Hacking USB HID for Easy Tethered Ubicomp

At this years Sketching in Hardware conference, I gave a talk on the general approach I used to create LinkM, ThingM’s USB-to-I2C adapter for programming and controlling BlinkMs. I called it “Hacking USB HID for Easy Tethered Ubicomp” (4.8MB PDF) to give it a form that fit within some of the larger issues I’ve been dealing with in creating easily usable ubiquitous computing devices.

USB has many different (and confusing) aspects to it. I’ve long advocated the creation of a set of libraries and patterns to make “driverless” USB a reality. A sort of training wheels for USB. At the time I called this USB on Rails”, poking fun at RoR.

To me the key to this ease-of-use was the HID class in USB. No driver is needed when plugging in something like a mouse or keyboard. Other built-in device class drivers include CDC (modems), Mass storage, audio (headset), and video (webcam).

While researching HID, trying to make LinkM a “USB on Rails” project, I found that the biggest hurdle was a consistent host-side USB API that would let one write one set of code that could easily be ported to Mac OS X, Windows, and Linux. Libusb works well enough for Unix-like OSes like Linux and Mac OS X, but the Windows variant libusb-win32 required a driver install. So I put HID away.

For many months I investigated using CDC instead of HID because it maps down to a serial port on modern operating systems. Unfortunately, CDC has two main problems. For the “serial port emulation” mode, mapping to serial port semantics is problematic for a USB device that can be removed at will. If a device is removed while it is still “connected”, the OS and application can get confused or crash. Also, the CDC driver implementation seems brittle on Mac OS X. Some CDC devices can work fine, others wouldn’t. I can see now why FTDI and similar vendors use a custom driver for their USB-to-serial chips.

When looking back into HID after the frustration with CDC, I discovered that V-USB, the software-only USB firmware stack for AVR microcontrollers, had two interesting HID-based projects in them with a cross-platform host-side library for talking HID. The first was BootloadHID, a HID-based bootloader, and the second was “hid-data”, one of the examples. And there was a nice discussion of the platform differences on the V-USB wiki.

With that, I took both of those projects, generalized them slightly, then specialized them for LinkM and made them the core of the LinkM project. You can view the resulting source at the LinkM Googlecode project.