Small but Serious ‘duino

Using my personal Arduino Uno R3 to set up a hard interface on a vehicle. This is actually work that I’m doing at home on a weekend, unpaid. Talk about loving my job!

I can’t give any details about the project I’m working on, but I wanted to share this simple, yet not so simple to accomplish, task.
Having a multi-platform HMI software based on Adobe’s Flash and AIR frameworks, and needing to wire it to a hardware interface (i.e. buttons) onboard, is not an overly complex task, and there are several ways to get it over with. In my case, since I only need one button with no feedback (such as status lights and the like), I decided to emulate a simple keyboard with my Arduino Uno R3 board. This way no drivers are involved, and no daemons need to be running on the machine to let the USB/Serial port and Flash talk.

Now, I know there are tutorials out there for the task of transforming your Arduino Uno R3 into a PnP USB Keyboard, but I like to write, and I wish to share any difficulties I might encounter while setting up my old MacBook Pro and OSX Mountain Lion as a DFM development machine.

So, step one has been opening Google. And I landed on this post by Phil Bambridge.

While scrubbing through his post, I went directly to the Arduino sketch, since I figured I wouldn’t be able to load it after I hacked the front end chip (the Atmel16U2 USB/TTL interface). Here is what I have come up with, a simple 1-button keyboard. At the time of writing, I haven’t yet tested this sketch. This is real-time blogging!

 

/*
  Arduino USB Keyboard HID
  Send Key "f" or "F" HID Usage ID: 09

  Keypress will trigger:
  - Resume rolling demo (if in manual mode)
  - Skip scene (if in rolling mode)
*/

#include <SoftwareSerial.h>

uint8_t buf[8] = {0}; /* Keyboard report buffer */

#define PIN_PUSHBUTTON 5
#define KEY_F_ID 9

int switch_F_State = 1;

void setup()
{

  Serial.begin(9600);
  pinMode(PIN_PUSHBUTTON, INPUT);

  delay(200);

}

void loop()
{

  int new_Switch_F_State = digitalRead(PIN_PUSHBUTTON);

  if(new_Switch_F_State == HIGH && switch_F_State == LOW) {
    buf[2] = KEY_F_ID; // The HID Usage ID for key f/F
    Serial.write(buf, 8); // Send keypress
  } else if(new_Switch_F_State == LOW && switch_F_State == HIGH) {
    buf[0] = 0;
    buf[2] = 0;
    Serial.write(buf, 8); // Send keyrelease
  }

  switch_F_State = new_Switch_F_State;

}

 

OK, before I decided to move to the next step I loaded a slightly different version of the sketch: I used simple write commands on the serial port, echoing some text like “pressed” and “released” that I could monitor on my computer. It all looks good.
BTW, to make this work, I used the simplest of wiring diagrams: a temporary pushbutton connected in serial with a 10kOhm resistor between +5V and GND, with a wire connecting the negative side of the switch to digital pin 5 on the Arduino board.

Time has come for da good stuff. Let’s look at updating the firmware in the USB/TTL chip.
So what we need is to install a dfu-programmer. Some will download the source, and use make to install it. I have encountered a number of problems with make on my Mac, every time. So I went on and installed MacPorts, which takes care of dependencies and installations, pretty much like you’d delegate these tasks to apt-get on Linux.
Once MacPorts is installed, you simply go on and install libusb (dunno if it was necessary, I installed it while trying to get the darn make to work) and dfu-programmer as such:

 

$ sudo port install libusb

$ sudo port install dfu-programmer

 

Now that you have dfu-programmer installed, you might want to check whether it can see your Arduino Uno R3 board in DFU mode.
To do so, just plug in your Arduino with the USB cable, and reset the ATmega16U2 chip. This is accomplished by shorting (aka bridging) the two ISCP pins closest to the USB connector briefly. You will notice the board rebooting as the control LED (pin 13) will switch off and on again.

At this point if you check with the Arduino IDE, you won’t be able to find the board anymore. Don’t panic, DFU mode is only temporary, just unplug and re-plug the board and you will see it again :)

To see if your version of dfu-programmer is good, you must try to erase the firmware in the ATmega16U2 chip, as so:

$ sudo dfu-programmer at90usb162 erase

The program will likely return an error on the likes of “dfu-programmer: no device present.”. This means that your installation still has the wrong device ID configured for this chip.
I say wrong because in our case it doesn’t work: it’s probably meant for something else. Either way… we need to fix it manually at this point.

Now, here is where I go off book, since I can’t seem to manage to make a source installation work without MacPorts, I actually dig deep in it’s installation folder, modify the configuration files and launch the make install command from there to “patch” the installation.

In my case, the installation folder is: /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_tarballs_ports_cross_dfu-programmer/dfu-programmer/work/dfu-programmer-0.5.4/
You simply search for “dfu-programmer” in Spotlight and you should be able to find the installation source files. MacPorts installs them under /opt/local/var/macports/ anyway.

What I did at this point was open the aforementioned folder, then it’s src subfolder and modified two files. The first one is Arguments.c, to which I added this line, at line 75 (note that you will need Super User privileges to overwrite the file, so either use a cool app like TextMate, or go the command line way, with nano):

 

{ "at90usb162_r3",  tar_at90usb162_r3,  adc_AVR,   0x2FEF, 0x03eb, 0x04000, 0x1000, true,  128, true,  false, 128, 0x0200 },

 

This is basically a copy of the “at90usb162″ line (which corresponds, or should correspond to the ATmega16U2 chip), but with a different ID (0x2FEF instead of 0x2FFA). Instead of overwriting the original line, I suppose it’s always a good idea simply to add a new one :)

The next file to modify is Arguments.h, to which we add the target, at line 53:

 

tar_at90usb162_r3

 

Now just open a terminal window, cd your way to the source folder (yes, always the same one stated earlier) and launch the installation commands:

 

$ sudo make
$ sudo make install

 

That will do the trick and patch the faulty dfu-programmer installation. After that, simply call dfu-programmer from the command line: it will printout a list of supported devices, and our at90usb162_r3 should show up.

Now try again to erase the firmware in the ATmega16U2 chip on your board, this time using the new device name. It shouldn’t take but a couple seconds.

 

$ sudo dfu-programmer at90usb162_r3 erase

 

This will clear the chip, then cd your way to where you saved the USB Keyboard firmware hex file, and launch the flash command:

 

$ sudo dfu-programmer at90usb162_r3 flash Arduino-keyboard-0.3.hex

 

It will be almost instant. Now, take a deep breath… unplug your Arduino. Plug it back in, and look at the Keyboard setup wizard :)
Go to any window with a text input, closest thing available is the terminal window you were operating. Give it focus, and press the pushbutton on your Arduino. You will see the letter “f” being typed.

Nice job, enjoy!!



Leave a Reply

You must be logged in to post a comment.