Some similar and confusing Spanish words

While trying to learn Spanish, I find a few Spanish words are similar to other words and keep confusing me. This article summarizes them, mostly for my on benefit in learning to distinguish them, but maybe you'll find it useful too. (Yes, this is a big tangent from my usual blog topics.)
  • llegar - to arrive.
  • llenar - to fill. (My secret to remembering this is that llenar is the root in chile relleno, a stuffed chile.)
  • llevar - to carry.
There are some verb conjugations that are the same or confusingly similar to other words:
  • fuera - outside.
  • fuera - imperfect subjunctive of ser or ir.
  • siento - I sit (from sentar).
  • siento - I feel (from sentir). A bunch of other conjugations are confusing because the present for one is the subjunctive for the other: sientas/sientes, sienta/siente, sienten/sientan, sentamos/sentimos.
  • ira - anger.
  • irá - future of ir.

Detecting an IR Beam Break with the Arduino IR Library

One reader asked how to use my Arduino Infrared Library to detect breakage of an IR beam. The answer was too long for the comments section, so I've extended into a blog post. One straightforward way is to use the library to modulate an IR LED at 38kHz, and use a standard IR detector module to detect the signal. The output from the module can be simply read as a digital input.

Here is a simple sketch to do that. The IR LED is connected to pin 3 through a 100 ohm resistor, the detector is connected to pin 2, and a status LED is connected to pin 13 (if your Arduino board doesn't have it already.) To create the modulated output, simply call irsend.enableIROut(38); to set the PWM to 38kHz, and then irsend.mark(0) to send a mark (i.e. turn the output on). The loop simply reads the input from the detector, inverts it (since the detector is active-low), and writes it to the status LED.

#include <IRremote.h>

#define PIN_IR 3
#define PIN_DETECT 2
#define PIN_STATUS 13

IRsend irsend;
void setup()
{
  pinMode(PIN_DETECT, INPUT);
  pinMode(PIN_STATUS, OUTPUT);
  irsend.enableIROut(38);
  irsend.mark(0);
}

void loop() {
  digitalWrite(PIN_STATUS, !digitalRead(PIN_DETECT));
}
You should see the pin 13 LED light up when the IR receiver detects an infrared signal, and go dark when the receiver does not detect an infrared signal. The circuit is basically trivial, but there's a schematic at my original article if you need one. The following picture shows the detector setup. Note the illuminated status LED.
IR detector circuit
If the circuit doesn't work, first use a cell phone camera to verify that the infrared LED is lit. If the LED is not lit, try reversing it. Here's my cellphone's view of the illuminated LED:
illuminated infrared LED
Next, point a TV remote control at the detector and make sure the status LED flashes. If the status LED doesn't come on, make sure you wired the detector properly, and connected to input 2 of the Arduino. If the status LED won't turn off when you break the beam, you probably aren't blocking the IR signal well enough. The detector is very sensitive, and IR bounces off many things, so you may need to separate the LED and detector by several feet and make sure you're fully blocking the IR beam. Note that the library assumes you're using a ATmega168/328, so you're on your own if you have a different processor.

The tricky part of this is the optics - figuring out how to set up the LED and receiver so the beam gets interrupted when you want it to. Also, you'll probably want to modify the detection logic to do something more interesting than just set the status LED, but that's left as an exercise for the reader :-)

Fixing my Concertmate MG-1 Synth

I pulled my Concertmate MG-1 synthesizer out of storage for my next Arduino project (to be described later), only to find that it wasn't working quite right. This posting briefly describes how I fixed it, in case anyone else has a similar problem.
Concertmate MG-1 Synthesizer
The main problem with the MG-1 was a loud click (a bit like a kick drum) when I pressed or released a key. It sounded suspiciously like a DC signal being applied to a speaker. The second problem was that when I set the contour for an attack and decay, the note got louder and softer, but as the note got softer it was replaced with a buzz at the frequency of oscillator 1.

Conveniently, the Service Manual is available online. I studied it and the schematic, and my first guess was that there was a DC offset going into the CA3080 amplifier, resulting in an amplified DC signal in the output. The CA3080 is not a normal amplifier but an operational transconductance amplifier, an unusual amplifier where the current on a control input controls the amplification of the input signal (more info). In this case, it is used as a voltage-controlled amplifier, allowing the contour signal to control the output.

In the schematic below, op-amps U10A and U10B feed the differential output signal into the 38080 amplifier. Pin 5 of the 3080 receives the contour signal to provide the attack and decay when you press a key. This signal controls how much the inputs are amplified. The output goes into the master volume control, and then to the synthesizer outputs. If there's a DC offset between the input pins 2 and 3, there will be an amplified DC offset at the output.
MG-1 Output Schematic
Fortunately, there is a VCA Balance Trim adjustment to trim any DC offset, and the manual describes how to adjust this. I opened up the MG-1 and adjusted this, but unfortunately it made no difference at all.

Next, I stared at the schematic for the contour generator that feeds into the CA3080 amplifier, but couldn't see how that could be going wrong. I measured the inputs to the CA3080 with an oscilloscope and found they all seemed normal. However, the output showed a 3.75V DC jump when the key turned on, which explained the click. In addition, the contour input showed it was picking up some crosstalk from the oscillator 1 trace that runs next to it, and this was being amplified into the buzzing noise.

All signs pointed to a problem with the CA3080 amplifier chip, which was somehow amplifying a big DC signal. Unfortunately, the CA3080 is no longer being manufactured and is hard to obtain. Fortunately, by some bizarre twist of fate, I happened to have one in my rather small box of parts.

The picture below shows the two main circuit boards. The upper board is the sound generation, filtering, and amplification, while the lower board has the power supply, keyboard, control, and polyphonic sound.
MG-1 internals
I removed the circuit board, soldered in the new CA3080, got the switches centered just right so the circuit board could be replaced, and put it back together. Unfortunately, I didn't get any output at all. I was afraid I'd somehow destroyed my rare CA3080 chip, but fortunately discovered that if the switches are in intermediate positions, you don't get any signal. I returned the switches to their proper positions and all was well.

In conclusion, I succeeded in fixing my MG-1 and getting that lovely, rich Moog sound.

Don't walk! Controlling a pedestrian sign with an Arduino

My latest project is controlling a pedestrian sign with an Arduino, so it will automatically step through the states of walk, flashing don't walk, and solid don't walk. In addition, I added infrared remote control support so I can use a remote control to turn the sign on and off, set it to a particular state, or start the cycle.

The hardware

A pedestrian sign controlled by an Arduino.
The pedestrian sign is controlled by two relays that switch 120-volt AC on and off; one powers the "walk" part of the sign, and one powers the "don't walk" part.
The Arduino circuitry.
The Arduino drives the relays through transistors connected to 9-volt supply. Technically the relays are 12-volt relays, but they seem to work with 9 volts. I used one 10A relay, and one 5A relay, just because that's what I had around.
The relays controlling the sign.
Needless to say, 120 volts can be dangerous, both to yourself and to your Arduino. Follow the appropriate precautions. I make no claims about the safety of this circuit.

The remote control input uses an IR detector module connected to the Arduino. For details on the IR detection, see the article on my IRremote library. The code section below describes how to modify the code to support different remotes.
Schematic of the pedestrian sign controller.

I found the IR detector didn't work super-reliably when the sign was turned on. This was probably due to high-frequency electrical interference since adding some capacitors helped, but the light itself could have been interfering. I probably should have wired up the relay circuit and the IR detector circuit farther apart to minimize interference, as I did when controlling a DC motor.

Inside the pedestrian sign

You may be curious about what's inside a pedestrian sign. What I have is the lighting unit; this goes inside the metal case that you see attached to a traffic pole. (In case you're worried, I didn't steal this from an intersection. I got it on ebay from some city that was replacing their units with more efficient LED units.)

Inside the signal are two neon tubes, roughly the shape of the hand and the pedestrian; generating red and white light respectively. I use "neon tube" in the generic sense; I don't know what gas is actually inside. Note that the tubes are not colored and the cover is clear; the red color is entirely from the gas discharge.
The neon tubes the pedestrian sign
Beneath the tubes are two high-voltage driver circuits, one for each tube. Each driver circuit runs off 120V AC and has an oscillator (using a LM2903 comparator) driving a flyback transformer through a power transistor (under the board). This generates multi-kilovolts to drive the tubes. Note at the far left the standoffs that keep the output wire an inch above the circuit board due to the high voltage. Needless to say, I stay away from the circuitry while it is operating. Each driver board has a separate AC input; when AC is fed in, the tube lights up. One drawback of the driver circuitry is it makes a high-pitched whine when turned on. I originally planned to use the sign to indicate unittest pass/fail status, but it was too annoying to people nearby.
The power circuits for the pedestrian sign

The code

The Arduino code is available at IRtraffic.pde and has two main functions: IR processing and light cycle processing.

In the IR code, the IR remote is used to select one of five states: walk illuminated, blinking don't walk, don't walk illuminated, off, or cycling (which goes through the first three states). The IR functionality uses my IRremote library to decode the output from a remote control.

The code has the values for a particular remote control hard-coded. I used a Sony DVD remote:

#define OFF_CODE 0x1CB92 // Stop on Sony DVD remote
#define WALK_CODE 0xB92 // 1 on Sony DVD remote
#define BLINK_CODE 0x80b92 // 2 on Sony DVD remote
#define DONT_CODE 0x40b92 // 3 on Sony DVD remote
#define CYCLE_CODE 0x4CB92 // Play on Sony DVD remote
The first part of the loop function calls the IR library to see if an IR signal has been decoded. If so, it switches to the appropriate mode. If an unexpected IR value is encountered, it is printed to the serial port.
void loop() {
  // Process the IR input, if any
  if (irrecv.decode(&results)) {
    if (results.value == WALK_CODE) {
      Serial.write("Walk\n");
      mode = MODE_WALK;
      cycle = false;
    } 
    else if (results.value == DONT_CODE) {
      Serial.write("Don't walk\n");
      mode = MODE_DONT;
      cycle = false;
    } 
    else if (results.value == OFF_CODE) {
      Serial.write("Off\n");
      mode = MODE_OFF;
      cycle = false;
    } 
    else if (results.value == BLINK_CODE) {
      Serial.write("Blinking don't walk\n");
      mode = MODE_BLINK;
      blinkOn = true;
      nextBlinkMillis = millis() + 500; // 500 ms blink
      cycle = false;
    } 
    else if (results.value == CYCLE_CODE) {
      Serial.write("Cycle\n");
      nextCycleMillis =  millis() + 5000; // delay 5 seconds
      cycle = true;
      mode = MODE_WALK;
    } 
    else {
      Serial.print("unexpected value: ");
      Serial.println(results.value, HEX);
    }
    irrecv.resume(); // Resume decoding (necessary!)
  }
If you want to use a different remote, simply look at the "unexpected values" printed to the serial port while pressing the desired buttons, copy the hex values into the code, recompile, and reinstall. For instance, to use some Tivo buttons, simply change the button definitions to:
#define OFF_CODE 0x20df10ef
#define WALK_CODE 0xa10cd00f
#define BLINK_CODE 0xa10c8807
#define DONT_CODE  0xa10cc807
#define CYCLE_CODE 0xa10c6c03
The other main function of the code is timing. There are two timing cycles going on. First, if cycle mode is enabled, the mode is advanced through walk, blink, and don't walk every five seconds. Second, if in the blinking don't walk phase, the output is turned on or off every half second.

I originally used delays of 500 or 1000 ms for the timing, but this had the disadvantage that the light wasn't very responsive to the remote control - it would wait up to 1 second before processing the remote control value. I rewrote the code using the BlinkWithoutDelay approach. In this approach, there are no delays in the loop code. Instead, the millis() value is checked to see if it is time to change state. If nothing needs to be done, loop() ends without any delay.

In more detail, the boolean cycle is true if the light is to cycle between the three phases. In this case, nextCycleMillis is set to the time at which we move to the next cycle (i.e. 5 seconds in the future). Once we reach that time, the mode is advanced. The boolean blinkOn keeps track of whether the don't walk sign is on or off while blinking.

  if (cycle && millis() >= nextCycleMillis) {
    if (mode == MODE_WALK) {
      mode = MODE_BLINK;
      blinkOn = false;
      nextBlinkMillis = millis() + 500; // 500 ms blink
      nextCycleMillis = millis() + 5000; // delay 5 seconds
    } 
    else if (mode == MODE_BLINK) {
      mode = MODE_DONT;
      nextCycleMillis =  millis() + 5000; // delay 5 seconds
    } 
    else {
      mode = MODE_WALK;
      nextCycleMillis =  millis() + 5000; // delay 5 seconds
    }
  }
The other independent time is nextBlinkMillis. This is the time at which the don't walk sign should change state, and it is set 500ms into the future.
  if (mode == MODE_BLINK && millis() >= nextBlinkMillis) {
    blinkOn = !blinkOn;
    nextBlinkMillis = millis() + 500; // 500 ms blink
  }
The code may be confusing at first due to the two independent times (nextCycleMillis and nextBlinkMillis) and state variables (mode and blinkOn). It seemed simpler this way rather than folding both cycles into one.

Finally, the code sets the appropriate lights on or off:

  if (mode == MODE_WALK) {
    digitalWrite(DONT_PIN, LOW);
    digitalWrite(WALK_PIN, HIGH);
  } 
  else if (mode == MODE_DONT || (mode == MODE_BLINK && blinkOn)) {
    digitalWrite(DONT_PIN, HIGH);
    digitalWrite(WALK_PIN, LOW);
  } 
  else {
    digitalWrite(DONT_PIN, LOW);
    digitalWrite(WALK_PIN, LOW);
  } 

Conclusion

I have two extra pedestrian signs; I'll give them away for free if you can pick them up in the SF Bay Area.

Using arbitrary remotes with the Arduino IRremote library

My IRremote library decodes output from many infrared remotes: Sony, NEC, RC5, and RC6. However, many remotes use other protocols. While it's not too hard to add support for other protocols, I wanted to show how the library can be used with arbitrary remote controls.

This post describes a simple routine that will generate a unique code for each key on an arbitrary remote. The demo application flashes the LED the appropriate number of times when I push the 0-9 button on my remote.

How it works

The IRremote library records the duration of each (modulated) pulse sent by the remote control. Each key on the remote corresponds to a particular code value, which is converted to a particular sequence of pulses. If you know the encoding algorithm, you can determine the code value, and thus the key pressed. However, for many applications it doesn't really matter what the original code value is, as long as you can uniquely distinguish each key. Thus, if you can turn each unique sequence of pulses into a unique value, then this value will indicate the desired key.

To do this, I look at the duration of successive pulses. If the pulse is shorter than the previous, I assign 0. If the pulse is the same length, I assign 1. If the pulse is longer, I assign 2. (I compare on-durations with on-durations and off-durations with off-duations.) The result is a sequence of 0's, 1's, and 2's. I hash these values into a 32-bit hash value.

With luck, the 32-bit hash value will be unique for each key. Note that these hash values are arbitrary, and don't have any obvious connection with the underlying code value. Most encoding protocols use two different durations, so comparing shorter vs longer will work, but you can imagine a code with multiple duration values that wouldn't work here. In addition, hash collisions could occur, but are pretty unlikely with a 32-bit hash.

Code

The code can be downloaded from IRhashcode.pde. The sample application prints the "real" decoded value and the hash value. The "real" value will only work for supported protocols (Sony, RC5, RC6, NEC), but the hash value should work for almost any remote control.

The code is pretty straightforward. compare() compares the two measured durations within the 20% tolerance.

int compare(unsigned int oldval, unsigned int newval) {
  if (newval < oldval * .8) {
    return 0;
  } 
  else if (oldval < newval * .8) {
    return 2;
  } 
  else {
    return 1;
  }
}
The actual decoding is fairly simple. results->rawbuf holds the measured durations as space, mark, space, mark, ... The loop compares each duration with the next of the same type, and adds that value to the hash result.
#define FNV_PRIME_32 16777619
#define FNV_BASIS_32 2166136261
unsigned long decodeHash(decode_results *results) {
  unsigned long hash = FNV_BASIS_32;
  for (int i = 1; i+2 < results->rawlen; i++) {
    int value =  compare(results->rawbuf[i], results->rawbuf[i+2]);
    // Add value into the hash
    hash = (hash * FNV_PRIME_32) ^ value;
  }
  return hash;
}
The mystery FNV numbers come from the FNV 32-bit hash function, which combines all the values into a single 32-bit value.

The following example code prints out the "real" decoded value and the hash decoded value to the serial port. You will want to use this code to figure out what hash value is associated with each key on the remote.

void loop() {
  if (irrecv.decode(&results)) {
    Serial.print("'real' decode: ");
    Serial.print(results.value, HEX);
    Serial.print(", hash decode: ");
    Serial.println(decodeHash(&results), HEX);
    irrecv.resume(); // Resume decoding (necessary!)
  }
}
Here's a slightly more realistic example. It receives a code from a Philips remote and flashes the LED appropriately. If you press "1", it flashes once, if you press "8" it flashes 8 times, etc. The code simply uses a case statement to match against the pressed key, and blinks that many times.

You will need to modify this to work with your remote. If it doesn't recognize the code, it will print it to the serial output. Put these unrecognized values into the code to make it work with your remote.

#define LEDPIN 13
void blink() {
  digitalWrite(LEDPIN, HIGH);
  delay(200);
  digitalWrite(LEDPIN, LOW);
  delay(200);
}  

void loop() {
  if (irrecv.decode(&results)) {
    unsigned long hash = decodeHash(&results);
    switch (hash) {
    case 0x322ddc47: // 0 (10)
      blink(); // fallthrough
    case 0xdb78c103: // 9
      blink();
    case 0xab57dd3b: // 8
      blink();
    case 0x715cc13f: // 7
      blink();
    case 0xdc685a5f: // 6
      blink();
    case 0x85b33f1b: // 5
      blink();
    case 0x4ff51b3f: // 4
      blink();
    case 0x15f9ff43: // 3
      blink();
    case 0x2e81ea9b: // 2
      blink();
    case 0x260a8662: // 1
      blink();
      break;
    default:
      Serial.print("Unknown ");
      Serial.println(hash, HEX);    
    }
    irrecv.resume(); // Resume decoding (necessary!)
  }
}

Debugging

The most likely problem is a key will occasionally have different code values. This is likely due to random errors in measuring the pulses. The code considers any durations within +/- 20% to be equal; you can try increasing this value.

If you're using a RC5/RC6 remote, each key will alternate between two different values. In that case, you probably want to use the "real" decoded value, rather than the hashed value, since you can mask out the toggle bit.

If your remote uses a protocol with multiple duration values, you probably won't get unique values from this algorithm.

For other problems, see the IRremote page, which also has a schematic for wiring up the IR detector.

Conclusion

This IR hash algorithm extends the IRremote library to be usable with many more types of infrared remote controls. Please let me know if you use it, and I'll add a link to your project if you want.

Arc beats Python for a web-controlled stereo

I recently set up a web interface to my stereo, implementing it in both Python and Arc. I found that, much to my surprise, writing the Arc implementation was much easier than the Python implementation in this case.

In my stereo controller system, I go to a web page that has an image of the appropriate remote control, and click the button. The Javascript in the web page sends a hex code back to the server, which sends the code to an Arduino microcontroller board, which converts the code into an infrared signal. The stereo interprets this signal as a command from the remote control and performs the desired action. It sounds complicated, but it responds quickly, even if I use the browser on my cell phone. I wrote up more details on the system earlier.
Remote control on G1 phone
The web server for this project is fairly straightforward: it needs to serve some static HTML pages and images, and needs to receive POST messages and forward the data over the serial port to the Arduino. I originally wrote the code in Python:

import cgi
import serial

from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler

class MyHandler(SimpleHTTPRequestHandler):
  def do_POST(self):
    if self.path == '/arduino':
      form = cgi.FieldStorage(fp=self.rfile, headers=self.headers,
        environ={'REQUEST_METHOD':'POST'})
      code = form['code'].value
      print 'Sent:', code
      arduino.write(code)
      self.send_response(200)
      self.send_header('Content-type', 'text/html')
      return
    return self.do_GET()

arduino = serial.Serial('/dev/ttyUSB0', 9600, timeout=2)
server = HTTPServer(('', 8080), MyHandler).serve_forever()
The Python web server is based on SimpleHTTPServer. To handle POST requests to the /arduino URL, I made a simple handler subclass that pulls the data out of the response, sends it to the serial port, and returns a blank response. The last two lines open the serial port and start up the server. The static web page serving comes "for free."

After writing this, I decided to try writing a version in Arc:

(= srvops* (table))

(= arduino-serial (outfile "/dev/ttyUSB0" 'binary))

(defopr || req "/index.html")

(defop arduino req (w/stdout (stderr)
  (let code (arg req "code")
    (write code arduino-serial)
    (prn "Sent code:" code))))

(thread (serve 8080))
Since you may not be familiar with the Arc web server, I'll give a brief explanation. The first line clears out the server's default pages (login, whoami, prompt, etc) that make sense for news.yc, but not for me. The next line opens the serial port. Next, the mysterious || redirects the home page. The next four lines are the handler for "/arduino": the "code" parameter is pulled out of the request (req). The code is written to the serial port, and printed to the log. The last line starts a serving thread on port 8080.

I'm not going to count tokens since that's a silly metric, but the Arc code is a clear winner here. The first Python disadvantage is the hideous cgi.FieldStorage call to parse the POST data; apparently this is the way to do it, but it took me considerable time to get this right. The second Python disadvantage is the necessity to set up the return code and content-type for the response. I ended up with a browser-specific bug when I didn't have this right, since some Javascript interpreters expect a particular response. Arc automatically sends a valid response. The main Arc disadvantage is there's no real serial port support; the Arc code just opens the port and hopes for the best. On the other hand, Python's serial library lets you set the baud rate, timeouts, and other parameters.

Arc and Python have a few more minor differences. Python requires imports, which Arc doesn't. Arc has the silly clearing of srvops* to avoid unwanted pages. Starting the server thread is simpler in Arc but not as flexible.

To summarize, I found the Python code difficult and error-prone to write, and the Arc code was shorter and just worked. This was a surprise to me; usually I find Python straightforward and Arc gives me pain when I have to write a bunch of code for some trivial thing it doesn't support. (For example, generating a time string in my temperature monitoring.) In this case, however, Arc came out ahead. Perhaps this is because Arc's flagship application is a web server, so it handles web serving well.

Obviously this is a fairly trivial program - the complexity is actually in the Javascript code and the C++ code on the Arduino - so I'm not claiming this as an overall victory for Arc over Python. But it's still interesting to find Arc came out ahead in this case.

TV-B-Gone for the Arduino

I've ported the TV-B-Gone code to run on the Arduino board. If you haven't seen a TV-B-Gone, it's a cute gadget that you point at a TV that's bothering you, and it turns the TV off. Internally, it's an infrared remote that broadcasts more than 100 different off codes that work on almost any TV. I figured it would be interesting to get the TV-B-Gone running on the Arduino.
TV-B-Gone running on an Arduinio

Update (November 2010)

I have a new, improved version of the software. Details and download are here.

The software

I started with the TV-B-Gone firmware, which is available under Creative Commons license. The TV-B-Gone runs on an ATtiny85 microcontroller, not the ATmega328 used by the Arduino, so some porting was required. One tricky part of the port is the IR signals are generated using the low-level hardware timer for PWM (pulse-width modulation). Since the ATtiny85 runs at 8MHz, and the Arduino runs at 16MHz, the timing code needed to be re-written, both the 10us delay loop and the timer register operations. The quick summary is I'm using Timer 2, scaling the clock by 8, using OCR2A to control the frequency and OCR2B to control the duty cycle, and have output on pin 3 (OC2B). (You are not expected to understand this. See my article on Secrets of Arduino PWM for details of how these timers work.)
#define freq_to_timerval(x) (F_CPU / 8 / x - 1)
...
    pinMode(IRLED, OUTPUT);
    TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
    TCCR2B = _BV(WGM22) | _BV(CS21);
...
    OCR2A = freq; 
    OCR2B = freq / 3; // 33% duty cycle
Another tricky thing is the original firmware stores the IR codes in program space, not RAM. The microcontrollers use a Harvard architecture, which means they have separate memory and data paths for code and data, unlike normal processors that use a von Neumann architecture. Because RAM storage is so small on these microcontrollers, the IR codes are stored in program space, with the result you need to use special methods to access them, rather than normal C pointers. Program memory storage is indicated with the PROGMEM macro and pulled out of memory using special functions such as pgm_read_byte. This makes the code somewhat confusing, for example:
const struct IrCode *NApowerCodes[] PROGMEM = {
  &code_na000Code,
...
}

data_ptr = (PGM_P)pgm_read_word(NApowerCodes+i);  

The original firmware stores the codes as compressed indices into tables of durations. See the TV-B-Gone design for details. Unfortunately, the Arduino's compiler didn't like the zero-length array in the IrCode structure, so I needed to rewrite the long file of codes to include another level of indirection.

Apart from these factors, porting was straightforward, and I tried to keep the original code where possible. I ripped out all the power-up and watchdog code. I replaced the low-level serial code with the Arduino's Serial library. Finally, I packaged it up into an Arduino sketch, which you can download. (Update: get the improved version here.)

The hardware

The hardware is straightfoward. I use pin 13 for the status LED; some Arduinos conveniently have an LED already wired up. Pin 3 is the PWM output to the IR LED through a 100 ohm resistor. If you want more range, add a driver transistor and use multiple IR LEDs. Pin 0 (update: pin 5) selects North American or European codes; leave it unconnected for North America and ground it for European. Pin 1 (update: 2) is connected via a pushbutton to ground to trigger the code transmission. (Update: pins have changed in the new version.)

To use the Arduino TV-B-Gone, point the IR LED at your TV, push the button, and your TV should turn off when the circuit hits the right code, which could take up to a minute. The visible LED should flash for each code that is transmitted. If the circuit doesn't work, use a cellphone camera to verify that the IR LED is transmitting. Don't expect more than a few feet range unless you use a transistor to increase the power. The code will print debugging output to the serial port if you set DEBUG in main.h.

Summary

Is the Arduino TV-B-Gone practical? If you want a TV-B-Gone that you can carry around to amaze your friends, the kit or product is much more compact, has high-powered IR outputs for longer range, and is nicely packaged. However, the Arduino platform is convenient for experimenting, and many people already have it, so I expect people will find it interesting.

You might wonder why I'm not using my Arduino Infrared Library for this project. Actually, I plan to at some point, but I wanted to get the straightforward port working first. In addition, my library will need some extensions to support all the codes that the TV-B-Gone supports.

I hope you enjoy the Arduino TV-B-Gone, and remember to use it for good, not evil!

Controlling your stereo over the web with the Arduino infrared library

Here's how you can control your stereo over the web. Not only that, but any other electronics with a IR remote control can now be controlled through your browser. You can even use your smart phone's browser to control your stereo from across the room or around the world.
Remote control on G1 phone
This project has several pieces: a simple Python web server running on your computer, an Arduino with my infrared library, and an IR LED or other emitter. The Python web server provides a web page with a graphical remote control. Clicking on the web page sends a code to the web server, which sends it over the serial port to the Arduino, which sends it to the IR LED, which controls your device.

The web server

I used a rather trivial Python web server (based on SimpleHTTPServer) that performs two tasks. First, it provides the static HTML pages and images. Second, it receives the POST requests and sends them to the Arduino using the pyserial library.

The following code excerpt shows the handler that processes POSTs to /arduino by extracting the code value out of the POST data and sending it to the Arduino over the serial line. The Python server automatically provides static pages out of the current directory by default; this is how the HTML files and images are served. The code assumes the serial port is /dev/ttyUSB0, which is typically the case on Linux.

class MyHandler(SimpleHTTPRequestHandler):
  def do_POST(self):
    if self.path == '/arduino':
      form = cgi.FieldStorage(fp=self.rfile, headers=self.headers,
        environ={'REQUEST_METHOD':'POST'})
      code = form['code'].value
      arduino.write(code)
      self.send_response(200)
      self.send_header('Content-type', 'text/html')
      return
    return self.do_GET()

arduino = serial.Serial('/dev/ttyUSB0', 9600, timeout=2)
server = HTTPServer(('', 8080), MyHandler).serve_forever()
The server can be accessed locally at http://localhost:8080. You may need to mess around with your firewall and router to access it externally; this is left as an exercise for the reader. I found that using my cell phone's browser via Wi-Fi worked surprisingly well, and over the cellular network there was just a slight lag (maybe 1/3 second).

The Arduino code

The code on the Arduino is pretty simple. It reads a command from the serial port and makes the appropriate IR library call. Commands consist of a character indicating the type of code, followed by 8 hex characters. For instance, "S0000004d1" sends the code 4d1 using Sony protocol; this is "play" on my Sony CD player. "N010e03fc" sends 010e03fc using NEC protocol; this turns my Harman Kardon stereo on. The full code is here, but some highlights:
void processSerialCode() {
  if (Serial.available() < 9) return;
  char type = Serial.read();
  unsigned long code = 0;
  // Read 8 hex characters into code (omitted)
  if (type == 'N') {
    irsend.sendNEC(code, 32);
  } 
  else if (type == 'S') {
    // Send Sony code 3 times
    irsend.sendSony(code, 12);
    delay(50);
    irsend.sendSony(code, 12);
    delay(50);
    irsend.sendSony(code, 12);
  }
  // More code for RC5 and RC6
}
In more detail, the Arduino waits for 9 characters to be available on the serial port. It then parses the hex value and calls the appropriate IR library send routine. The Arduino code does some special-case stuff for the different code types. Sony codes are transmitted three times as the protocol requires. The RC5 and RC6 protocol uses a toggle bit that is flipped on each transmission. (Disclaimer: I don't have RC5/RC6 devices, so this code is untested.) If your device uses a different protocol that the library doesn't support, you're out of luck unless you add the protocol to the library. That's probably not too hard; a couple people have already implemented new protocols.
Arduino controlling stereo via IR

The web page

Most of the smarts of the system are in the web page. In my setup, I have a HK-3370 stereo, and a Sony CDP-CE335 CD player. I took a picture of the remote for each and used an HTML image map to make each button clickable. Clicking on a button uses Ajax to POST the appropriate IR code to the server.

I use Ajax to send the code to the server to avoid reloading the web page on every click. The Javascript code is verbose but straightforward. The first part of the code creates the XML request object; unfortunately different browsers use different objects. The next part of the code creates and sends the POST request. The actual data sent to the server is, for instance, "code=N12345678" to send 0x12345678 using NEC protocol.

function button(value) {
  if (window.XMLHttpRequest) {
   request = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    try {
      request = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
        request = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {}
    }
  }
  request.open('POST', '/arduino', true);
  request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  request.setRequestHeader('Content-length', value.length);
  request.setRequestHeader('Connection', 'close');
  request.send('code=' + value);
}
The clickable buttons are defined in the HTML through an image and an image map. Generating the image and the image map is the hard part of the whole project:
<img src="hk3370.png" width="268" height="800" border="0" usemap="#map" />
<map name="map">
<area shape="rect" coords="60,97,85,111" href="#" alt="on" onClick="button('N010e03fc')" />
<area shape="rect" coords="104,98,129,109" href="#" alt="off" onClick="button('N010ef906')" />
...
Each line in the map defines a region of the image as a button with a particular code. When clicked, this region will call the button function with the appropriate code, causing the code to be sent to the web server, the Arduino, and finally to the stereo. The alt text isn't actually used, but I recommend it to keep track of what button is associated with each line. The href causes the cursor to change when you go over the region, but isn't necessary.
Image of remote control in Internet Explorer

In this approach, the Arduino code and web server code are very simple, as they don't need to know the functions of the codes. A different way to implement this system would be to put the table of codes ("SONY_CD_ON" = 4d1, etc.) either in the web server code or the Arduino code.

To generate the web pages, I took a picture of the remote with my camera and cleaned up the picture with GIMP. I used the GIMP image map plugin to create the image map. I outlined each button, then filled in the URL with the appropriate IR code, and filled in the alt text with the name of the button. Finally, I copied the map file into the HTML file and edited it to use the Javascript function.

The easiest way to obtain the IR codes is to use the IRrecvDump example sketch included in my IR library. Simply press the button on your remote, see what code was sent, and put that code into the image map. Alternatively, you may be able to find codes in the LIRC database.

Once you get going, it's actually fairly quick to generate the image map. Select a button in the editor, click the physical button on the remote, copy the displayed value into the editor, and move on to the next button. As long as you don't get obsessive and start tweaking the regions to line up perfectly, it's pretty quick.

If you don't want to mess around with the image map, take a look at simple.html. This file shows how to use standard HTML buttons. Not as cool as the image, but much easier:

<input type="button" value="on" onClick="button('N010e03fc')" >
<input type="button" value="off" onClick="button('N010ef906')" >
...
Simple button arrangement

The hardware

The Arduino does the work of converting the hex code into an IR signal. The IR library uses digital PWM pin 3 as output, which must be connected to your IR emitter. I use a 100 ohm resistor to limit current. Wiring it up is trivial.
Schematic of IR connection to Arduino

I used a Tivo IR blaster that I had lying around, but a plain IR LED will work too. The following picture shows an IR blaster attached to my sterero. Note that the blaster needs to be positioned about the stereo's IR receiver; it may be easier to see the receiver with a flashlight.
IR blaster attached to stereo

Putting it all together

To summarize the steps:
  • Download the files and unpack them.
  • Get the infrared library and install it.
  • Aim the IR source at the device(s) to control, and connect it to the Arduino. (You may want to use a visible LED for testing.)
  • Connect the Arduino to the computer's USB port.
  • Compile and install IRwebremote.pde using the Arduino IDE.
  • Create HTML files for your remote controls. (This is the hard step.)
  • Run the Python server: python server.py
  • Go to http://localhost:8080 and control the devices.
This project has multiple pieces and requires customization, so it's not a plug-and-play project. I only recommend trying this if you know what you're doing. Good luck!

Lorem Ipsue: when internationalization goes bad

I recently saw a Master cable lock for sale with the interesting text "Lore Ipsum!" and "Lorem Ipsue!" underneath the word "Pull". If you've done any graphic design or web mockups, you're probably familiar with the Lorem ipsum text that's traditionally used as a placeholder. This Latin-based text is used, for instance, when you want to show the style and layout of a website, but don't want people to get distracted by the words.
Lock with text 'Lore ipsum' and 'Lorem ipsue'
Apparently when they designed the lock packaging, they put in placeholders but forgot to replace them with the French and Spanish translations ("Tirez!" and "¡Tira!"). I find "Lorem Ipsue!" in place of "Lorem Ipsum" interesting; maybe it is supposed to be a more Spanish-sounding placeholder, but I would have been more impressed by ¡Lorem Ipsum!

The moral is: make sure you check your internationalization; just because it looks foreign doesn't mean it's right.

Notes on dual-booting Windows 7 and Linux

Dual-booting Windows 7 and Linux is mostly straightforward, but I ran into a few problems. The following notes describe my setup, mostly for my own benefit.

If you're looking for a comprehensive dual-boot tutorial, try apc or Loko.

My setup

I'm running Windows 7 and Fedora 11 Linux on a Gateway SX2800.

Partitioning

I use the Gnome Partition Editior (GParted). Windows 7 conveniently includes a partition software under Disk Management, but inconveniently it can't shrink a volume by a large amount.

My partitioning setup is a bit crazy. Because I bought my computer before Windows 7 was released, I used Windows 7 beta until I got the official upgrade DVD. One unpleasant surprise is you have to reinstall to get from the beta to Windows 7 Home Premium; you can't just upgrade. I had an empty E: partition, so I installed the offical release there, transferred my files with Windows Easy Transfer, and then spent an evening reinstalling all my software. I store most of my data on a FAT32 partition D:to avoid messing around with NTFS on Fedora.

You'll probably want something simpler than what I have, but my partition table is:

$fdisk /dev/sda
...
   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1        1698    13631488   27  Unknown
/dev/sda2   *        1699       14445   102390277+   7  HPFS/NTFS
/dev/sda3           14446       27193   102398310    7  HPFS/NTFS
/dev/sda4           27194       77825   406701540    5  Extended
/dev/sda5           27194       28289     8803588+  82  Linux swap / Solaris
/dev/sda6           28290       70176   336457296    b  W95 FAT32
/dev/sda7           70177       77825    61440561   83  Linux
sda1 is a mysterious Gateway recovery partition, sda2 is C:, sda3 is E:, sda6 is D: for most of my data, and sda7 is the Linux partition.

/etc/fstab

/dev/sda7               /                       ext3    defaults        1 1
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
/dev/sda5  swap                    swap    defaults        0 0
/dev/sda6  /d   vfat auto,rw,user,sync,exec,dev,suid,uid=500,gid=500,umask=000 0 2

My GRUB config

default=1
timeout=5
splashimage=(hd0,2)/boot/grub/splash.xpm.gz
hiddenmenu
title Fedora (2.6.30.9-96.fc11.i586)
 root (hd0,6)
 kernel /boot/vmlinuz-2.6.30.9-96.fc11.i586 ro root=/dev/sda7 rhgb quiet
 initrd /boot/initrd-2.6.30.9-96.fc11.i586.img
title Windows 7
 rootnoverify (hd0,1)
 chainloader +1
Note the off-by-one: (hd0,6) boots off sda7. For Windows, you need to specify the partition with the Windows boot loader; if I try to boot E: directly with (hd0,2), I get BOOTMGR IS MISSING.

Editing the GRUB config from Linux rescue boot

Invariably I end up unable to boot Linux from my disk. To fix this, I boot from my Linux CD and then fix the GRUB config. The following assumes sda7 is the Linux partition:
mount /mnt /dev/sda7
cd /mnt/boot/grub
vi menu.lst
grub-install --root-directory=/mnt /dev/sda

Editing the Windows boot loader configuration

If you have multiple versions of Windows, you'll need to configure the Windows boot loader through bcdedit: details.

Other random errors

My Fedora Core boot failed with an infinite loop of "init: ttyx respawning too fast, stopped". The solution was to change selinux=enforcing to selinux=permissive in /etc/selinux/config.

Conclusion

The above notes are mostly for my own benefit the next time I need to configure GRUB, but maybe they'll help someone else. Disclaimer: it's very easy to lose data or mess up your system so it won't boot. Back everything up and make sure you have Linux and Windows rescue disks. Don't blame me if things go wrong.

IR Bubbles: Controlling a relay with an Arduino and an IR remote

An Arduino can be used to turn devices on and off via an infrared remote. As an entirely impractical example of how to use my Arduino infrared remote library to turn things on and off, I have set up my Arduino to turn a bubble maker on and off under remote control. The same techniques can be used to control an LED or anything else via IR remote.

Arduino blowing bubbles

The circuit is straightforward. An IR sensor is connected to the Arduino to detect the infrared signal. On the output side, I used a standard relay circuit. To control the bubble maker, I wired the relay in place of the power switch. A 5 volt source wasn't enough to close the relay I had handy, but 9 volts was. For this reason, I powered the Arduino off a 9V battery and connected the relay to Vin so the relay would get the full 9 volts. (A 9 volt AC adapter also works.)

Arduino IR relay schematic

The code

The following code controls the relay. Any detected IR code will toggle the output on or off. Press a button once on the remote and the output will turn on. Press a button again and the output will turn off. (You will, of course, need to download my Arduino infrared remote library to use this code.)
#include <IRremote.h>

int RECV_PIN = 11;
int OUTPUT_PIN = 4;

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
  pinMode(OUTPUT_PIN, OUTPUT);
  pinMode(13, OUTPUT);
  irrecv.enableIRIn(); // Start the receiver
}

int on = 0;
unsigned long last = millis();

void loop() {
  if (irrecv.decode(&results)) {
    // If it's been at least 1/4 second since the last
    // IR received, toggle the relay
    if (millis() - last > 250) {
      on = !on;
      digitalWrite(OUTPUT_PIN, on ? HIGH : LOW);
    }
    last = millis();      
    irrecv.resume(); // Receive the next value
  }
}
The above code only toggles the output if there is at least a 1/4 second (250 ms) gap since the last received signal. The motivation behind this is that remotes often repeat the signal as long as the button is held down, and we don't want the output to toggle continuously. One other thing to notice is the call to resume(); after a code is received, the library stops detection until resume() is called.

I should make it clear that although the above example uses a relay output, the relay is just for example. The above code will work with any arbitrary output: you can use it to control a LED or anything else that can be controlled by an Arduino output pin.

Using two buttons

Another way you might want to use an IR remote is have one button turn the output on, and another button turn it off. Here's the loop code to use a Sony DVD remote; the "play" button turns the output on, and the "stop" button turns the output off:
void loop() {
  if (irrecv.decode(&results)) {
    if (results.value == 0x4cb92) { // Sony DVD play
      digitalWrite(OUTPUT_PIN, HIGH);
    } 
    else if (results.value == 0x1cb92) { // Sony DVD stop
      digitalWrite(OUTPUT_PIN, LOW);
    }   
    irrecv.resume(); // Receive the next value
  }
}
Just remember that you have to call resume after all decodes, not just the ones you're interested in.

Getting the codes

You may wonder how I got the Sony codes. One way is to look at the appropriate LIRC config file. (At some point I'll write up a full explanation of the LIRC config files.) An easier way is to just dump out to the serial port the codes that your Arduino receives. Press the buttons on your remote, and read out the values received:
void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}

Using a specific button

A third way you might want to use an IR remote is to have a specific button toggle the output on and off. Here's code that uses the Tivo button on a Tivo Series 2 remote to toggle the output on and off. Again, you can get the button code from a LIRC config file, or by dumping the output to your serial port.
void loop() {
  if (irrecv.decode(&results)) {
    if (results.value == 0xa10ce00f) { // TIVO button
      // If it's been at least 1/4 second since the last
      // IR received, toggle the relay
      if (millis() - last > 250) {
        on = !on;
        digitalWrite(OUTPUT_PIN, on ? HIGH : LOW);
      }
      last = millis();
    }    
    irrecv.resume(); // Receive the next value
  }
}

The hardware setup

Arduino relay circuit

The hardware setup is pretty simple. The above photo shows the IR detector on the left, and the relay on the right. The drive transistor, resistor, and diode are behind the relay, and the blue terminal strip is in front. The black box to the right of the Arduino is a 9V battery holder. The box underneath is just to hold everything up.

You may wonder why I placed the input and output components so far apart, and why I didn't use the protoboard power and ground buses. It turns out that the motor on the bubble maker is a nasty source of RFI interference that would jam the IR detector's signal if the wires to the bubble maker came near the IR detector wiring. Capacitors didn't help, but distance did. Most likely this won't be a problem for you, but I figured I should mention it.

In conclusion, happy hacking with the infrared library. Let me know if you do anything interesting with it!

Simple genome analysis with Arc: In which I examine the XMRV genome and discover little of interest

I decided to examine the genome of the retrovirus XMRV to see what I could learn. This virus, with the absurd name Xenotropic Murine leukemia virus-Related Virus, was found a few years ago in many cases of prostate cancer and very recently found in many people suffering from chronic fatigue syndrome (more, more). If these studies turn out to be true, it would be quite remarkable that an obscure new retrovirus causes such differing diseases.

My goal was to take the XMRV genome (the sequence of c's, g's, a's, and t's that make up its RNA), and see if the combination "cg" is a lot more rare than you'd expect. This probably seems like a pretty random thing to do, but there's actually a biological reason.

One way the human immune system detects invaders is by looking for DNA containing a cytosine followed by a guanine (which is called a CpG dinucleotide). In mammals, most CpG dinucleotides are methylated (specially tagged), so any CpG that shows up is a sign of something invading. My hypothesis was that XMRV might have a very low number of CpG dinucleotides, helping it avoid the immune system and contributing to its ability to cause disease.

Conveniently, the genome of XMRV has been sequenced and can be downloaded, consisting of 8185 bases:

        1 gcgccagtca tccgatagac tgagtcgccc gggtacccgt gttcccaata aagccttttg
       61 ctgtttgcat ccgaagcgtg gcctcgctgt tccttgggag ggtctcctca gagtgattga
...
It would be a simple matter to use Python to count the number of CG pairs in the genome, but I figured using the Arc language would be more interesting.

The first step is to write a function to parse out the DNA sequence from the genome file; this consists of the lines between ORIGIN and //, with the spaces and numbers removed.

(def skip-to-origin (infile)
  (let line (readline infile)
    (if (is 'eof line) line ;quit on eof
        (litmatch "ORIGIN" line) line ;quit on ORIGIN
        (skip-to-origin infile)))) ; recurse

; Reads the data from one line
; Returns nil on EOF or // line
(def read-data-line (infile)
  (let line (readline infile)
    (if (is 'eof line) nil
        (litmatch "//" line) nil
 (keep [in _ #\c #\g #\a #\t] line))))

; Read the sequence data from ORIGIN to //
; Returns a single string
(def readseq (infile)
   (skip-to-origin infile)
   (string (drain (read-data-line infile))))
This code simply uses skip-to-origin to read up to the ORIGIN line, and then read-data-line to read the cgat data from each following line.

The next step is a histogram function to count the number of times each nucleotide occurs into a table. (Edit: I've shortened my original code with some advice from arclanguage.org.)

((def hist (seq)
  (counts (coerce seq 'cons)))
After downloading the genome as "xmrv", I can load the sequence into seq and generate the histogram:
arc> (= seq (w/infile inf "xmrv" (readseq inf)))
"gcgccagtcatccgatagactgagtcgcccgggtacccgtgt ...etc"
arc> (len seq)
8185
arc>(hist seq)
#hash((#\t . 1732) (#\g . 2057) (#\a . 2078) (#\c . 2318))
The sequence is 8185 nucleotides long as expected, with 1732 T's, 2057 G's, 2078 A's, and 2318 C's. To count the number of times each pair of nucleotides occurs, I made a more general function that will handle pairs or any other sequence of n nucleotides:
(def histn (seq n)
  (w/table h
    (for i 0 (- (len seq) n)
      (++ (h (cut seq i (+ i n)) 0)))
    h))
Since I got tired of looking at raw hash tables, I made a short function to format the output as well as generating percentages.
(def prettyhist (h)
  (let count (reduce + (vals h))
    (let sorted (sort (fn ((k1 v1) (k2 v2)) (> v1 v2))
                      (accum addit (each elt h (addit elt))))
      (each (k v) sorted
        (prn k ": " v " (" (num (* (/ v count) 100.) 2) "%)")))))
Running these functions:
arc> (prettyhist (histn seq 2))
cc: 862 (10.53%)
gg: 639 (7.81%)
ag: 616 (7.53%)
ct: 612 (7.48%)
aa: 588 (7.18%)
ga: 585 (7.15%)
ca: 537 (6.56%)
ac: 529 (6.46%)
tg: 494 (6.04%)
tc: 469 (5.73%)
gc: 458 (5.6%)
tt: 401 (4.9%)
gt: 375 (4.58%)
ta: 368 (4.5%)
at: 344 (4.2%)
cg: 307 (3.75%)
This shows that CG is the most uncommon combination, but not super-low. How does this compare to the frequence if the C/G/A/T frequency was the same, but they were ordered randomly? We can compute this by computing all the possibilities of taking two letters from the original sequence. Instead of actually summing all the combinations, we can just take the cross-product of the original histogram:
(def cross (h1 h2)
  (let h (table)
    (each (k1 v1) h1
      (each (k2 v2) h2
        (let combo (string k1 k2)
   (if (no (h combo))
     (= (h combo) 0))
   (= (h combo) (+ (h combo) (* v1 v2))))))
    h))
This gives us the result:
arc> (prettyhist (cross (hist seq) (hist seq)))
cc: 5373124 (8.02%)
ac: 4816804 (7.19%)
ca: 4816804 (7.19%)
cg: 4768126 (7.12%)
gc: 4768126 (7.12%)
aa: 4318084 (6.45%)
ag: 4274446 (6.38%)
ga: 4274446 (6.38%)
gg: 4231249 (6.32%)
tc: 4014776 (5.99%)
ct: 4014776 (5.99%)
at: 3599096 (5.37%)
ta: 3599096 (5.37%)
gt: 3562724 (5.32%)
tg: 3562724 (5.32%)
tt: 2999824 (4.48%)
This tells us that CG would appear 7.12% of the time if the sequence were randomly shuffled, but instead it appears only 3.75% of the time, so CG shows up about half as often as expected. This is in line with known results for the related MuLV virus, so it seems that there's nothing special about XMRV.

On the other hand, it's known that the HIV genome has a severely low amount of CpG:

arc> (prettyhist (histn (w/infile inf "hivbru" (readseq inf)) 2))
aa: 1096 (11.88%)
ag: 971 (10.52%)
ca: 766 (8.3%)
ga: 762 (8.26%)
at: 691 (7.49%)
ta: 665 (7.21%)
gg: 631 (6.84%)
tg: 548 (5.94%)
ac: 530 (5.74%)
tt: 524 (5.68%)
gc: 430 (4.66%)
ct: 428 (4.64%)
gt: 409 (4.43%)
cc: 381 (4.13%)
tc: 315 (3.41%)
cg: 81 (.88%)
I also took a look at the H1N1 flu sequences. The influenza genome is on 8 separate strands of RNA, so there are 8 separate sequences to process. (The HA segment is the "H" and the NA segment is the "N" in H1N1.) Many H1N1 sequences can be downloaded. I somewhat arbitrarily picked A/Beijing/02/2009(H1N1) since all 8 strands were sequenced. After saving the strands as flu1, ..., flu8, I ran the histogram on all the strands:
arc> (for i 1 8 (prn "---" i "---")
  (prettyhist (histn (w/infile inf (string "flu" i) (readseq inf)) 2)))
On all strands, "cg" was at the bottom of the frequency chart. Especially low-frequency strands are 1 (PB2) at 1.93% CpG, 2 (PB1) at 1.52%, 4 (HA) at 1.57%, and 6 (NA) at 1.77%. Strand 8 (NEP) was highest at 3.09%. So it looks like influenza is pretty low in CpG frequency, but not as low as HIV. (Edit: I've since found a paper that examines CpG in influenza in more detail.)

To conclude, Arc can be used for simple genome analysis. My original hypothesis that XMRV would have low levels of CpG dinucleotides holds, but not as dramatically as for HIV or H1N1 influenza. Apologies to biologists for my oversimplifications, and apologies to statisticians for my lack of p-values :-)

An Arduino universal remote: record and playback IR signals

I've implemented a simple IR universal remote that will record an IR code and retransmit it on demand as an example for my IR library. Handling IR codes is a bit more complex than it might seem, as many protocols require more than simply recording and playing back the signal.

To use the universal remote, simply point your remote control at the IR module and press a button on the remote control. Then press the Arduino button whenever you want to retransmit the code. My example only supports a single code at a time, but can be easily extended to support multiple codes.

The hardware

The IR recorder
The above picture shows the 9V battery pack, the Arduino board, and the proto board with (top-to-bottom) the IR LED, IR receiver, and pushbutton.

The circuitry is simple: an IR sensor module is connected to pin 11 to record the code, an IR LED is connected to pin 3 to transmit the code, and a control button is connected to pin 12. (My IR library article has details on the sensor and LED if you need them.)
Schematic of the IR recorder

The software

The code can be downloaded as part of my IRremote library download; it is the IRrecord example.

Handling different protocols

The code supports multiple IR protocols, each with its own slight complications:

Sony codes can be recorded and played back directly. The button must be held down long enough to transmit a couple times, as Sony devices typically require more than one transmission.

The common NEC protocol is complicated by its "repeat code". If you hold down a button, the remote transmits the code once followed by multiple transmissions of special repeat code. The universal remote records the code, not the repeat code. On playback, it transmits the code once, followed by the repeat code.

The RC5 and RC6 protocols handle repeated transmissions differently. They use two separate codes for each function, differing in a "toggle bit". The first time you hold down a button, the first code is transmitted repeatedly. The next time you hold down a button, the second code is transmitted repeatedly. Subsequent presses continue to alternate. The universal remote code flips the toggle bit each time it transmits.

The universal remote handles any other unknown protocol as a "raw" sequence of modulated IR on and off. The main complication is that IR sensor modules typically stretch out the length of the "on time" by ~100us, and shorten the "off time" correspondingly. The code compensates for this.

Most likely there are some codes that that can't handle, but it has worked with the remotes I've tried.

The code also prints debugging information to the serial console, which can be helpful for debugging any problems.

In conclusion, this is intended as a proof of concept rather than a useful product. The main limitation is supporting one code at a time, but it's straightforward to extend the code. Also note that the record and playback functions can be separated; if you know the IR codes you're dealing with, you can use just the necessary function.

A Multi-Protocol Infrared Remote Library for the Arduino

Code now on github

The most recent code is at github.com/shirriff/Arduino-IRremote. If you have any issues, please report them there.

Do you want to control your Arduino with an IR remote? Do you want to use your Arduino to control your stereo or other devices? This IR remote library lets you both send and receive IR remote codes in multiple protocols. It supports NEC, Sony SIRC, Philips RC5, Philips RC6, and raw protocols. If you want additional protocols, they are straightforward to add. The library can even be used to record codes from your remote and re-transmit them, as a minimal universal remote.

Arduino IR remote

To use the library, download from github and follow the installation instructions in the readme.

How to send

This infrared remote library consists of two parts: IRsend transmits IR remote packets, while IRrecv receives and decodes an IR message. IRsend uses an infrared LED connected to output pin 3. To send a message, call the send method for the desired protocol with the data to send and the number of bits to send. The examples/IRsendDemo sketch provides a simple example of how to send codes:
#include <IRremote.h>
IRsend irsend;

void setup()
{
  Serial.begin(9600);
}

void loop() {
  if (Serial.read() != -1) {
    for (int i = 0; i < 3; i++) {
      irsend.sendSony(0xa90, 12); // Sony TV power code
      delay(100);
    }
  }
} 
This sketch sends a Sony TV power on/off code whenever a character is sent to the serial port, allowing the Arduino to turn the TV on or off. (Note that Sony codes must be sent 3 times according to the protocol.)

How to receive

IRrecv uses an infrared detector connected to any digital input pin.

The examples/IRrecvDemo sketch provides a simple example of how to receive codes:

#include <IRremote.h>

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}
The IRrecv class performs the decoding, and is initialized with enableIRIn(). The decode() method is called to see if a code has been received; if so, it returns a nonzero value and puts the results into the decode_results structure. (For details of this structure, see the examples/IRrecvDump sketch.) Once a code has been decoded, the resume() method must be called to resume receiving codes. Note that decode() does not block; the sketch can perform other operations while waiting for a code because the codes are received by an interrupt routine.

Hardware setup

The library can use any of the digital input signals to receive the input from a 38KHz IR receiver module. It has been tested with the Radio Shack 276-640 IR receiver and the Panasonic PNA4602. Simply wire power to pin 1, ground to pin 2, and the pin 3 output to an Arduino digital input pin, e.g. 11. These receivers provide a filtered and demodulated inverted logic level output; you can't just use a photodiode or phototransistor. I have found these detectors have pretty good range and easily work across a room.

IR wiring

For output, connect an IR LED and appropriate resistor to PWM output pin 3. Make sure the polarity of the LED is correct, or it won't illuminate - the long lead is positive. I used a NTE 3027 LED (because that's what was handy) and 100 ohm resistor; the range is about 15 feet. For additional range, you can amplify the output with a transistor.

Some background on IR codes

An IR remote works by turning the LED on and off in a particular pattern. However, to prevent inteference from IR sources such as sunlight or lights, the LED is not turned on steadily, but is turned on and off at a modulation frequency (typically 36, 38, or 40KHz). The time when a modulated signal is being sent will be called a mark, and when the LED is off will be called a space.

Each key on the remote has a particular code (typically 12 to 32 bits) associated with it, and broadcasts this code when the key is pressed. If the key is held down, the remote usually repeatedly broadcasts the key code. For an NEC remote, a special repeat code is sent as the key is held down, rather than repeatedly sending the code. For Philips RC5 or RC6 remotes, a bit in the code is toggled each time a key is pressed; the receiver uses this toggle bit to determine when a key is pressed down a second time.

On the receiving end, the IR detector demodulates this signal, and outputs a logic-level signal indicating if it is receiving a signal or not. The IR detector will work best when its frequency matches the sender's frequency, but in practice it doesn't matter a whole lot.

The best source I've found for details on the various types of IR codes is SB IR knowledge base.

Handling raw codes

The library provides support for sending and receiving raw durations. This is intended mainly for debugging, but can also be used for protocols the library doesn't implement, or to provide universal remote functionality.

The raw data for received IR measures the duration of successive spaces and marks in 50us ticks. The first measurement is the gap, the space before the transmission starts. The last measurement is the final mark.

The raw data for sending IR holds the duration of successive marks and spaces in microseconds. The first value is the first mark, and the last value is the last mark.

There are two differences between the raw buffers for sending and for receiving. The send buffer values are in microseconds, while the receive buffer values are in 50 microsecond ticks. The send buffer starts with the duration of the first mark, while the receive buffer starts with the duration of the gap space before the first mark. The formats are different because I considered it useful for the library to measure gaps between transmissions, but not useful for the library to provide these gaps when transmitting. For receiving, 50us granularity is sufficient for decoding and avoids overflow of the gaps, while for transmitting, 50us granularity is more than 10% error so 1us granularity seemed better.

Obtaining codes for your remote

The easiest way to obtain codes to work with your device is to use this library to decode and print the codes from your existing remote.

Various libraries of codes are available online, often in proprietary formats. The Linux Infrared Remote Control project (LIRC), however, has an open format for describing codes for many remotes. Note that even if you can't find codes for your exact device model, a particular manufacturer will usually use the same codes for multiple products.

Beware that other sources may be inconsistent in how they handle these protocols, for instance reversing the order, flipping 1 and 0 bits, making start bits explicit, dropping leading or trailing bits, etc. In other words, if the IRremote library yields different codes than you find listed elsewhere, these inconsistencies are probably why.

Details of the receiving library

The IRrecv library consists of two parts. An interrupt routine is called every 50 microseconds, measures the length of the marks and spaces, and saves the durations in a buffer. The user calls a decoding routine to decode the buffered measurements into the code value that was sent (typically 11 to 32 bits).

The decode library tries decoding different protocols in succession, stopping if one succeeds. It returns a structure that contains the raw data, the decoded data, the number of bits in the decoded data, and the protocol used to decode the data.

For decoding, the MATCH macro determine if the measured mark or space time is approximately equal to the expected time.

The RC5/6 decoding is a bit different from the others because RC5/6 encode bits with mark + space or space + mark, rather than by durations of marks and spaces. The getRClevel helper method splits up the durations and gets the mark/space level of a single time interval.

For repeated transmissions (button held down), the decoding code will return the same decoded value over and over. The exception is NEC, which sends a special repeat code instead of repeating the transmission of the value. In this case, the decode routine returns a special REPEAT value.

In more detail, the receiver's interrupt code is called every time the TIMER1 overflows, which is set to happen after 50 microseconds. At each interrupt, the input status is checked and the timer counter is incremented. The interrupt routine times the durations of marks (receiving a modulated signal) and spaces (no signal received), and records the durations in a buffer. The first duration is the length of the gap before the transmission starts. This is followed by alternating mark and space measurements. All measurements are in "ticks" of 50 microseconds.

The interrupt routine is implemented as a state machine. It starts in STATE_IDLE, which waits for the gap to end. When a mark is received, it moves to STATE_MARK which times the duration of the mark. It then alternates between STATE_MARK and STATE_SPACE to time marks and spaces. When a space of sufficiently long duration is received, the state moves to STATE_STOP, indicating a full transmission is received. The interrupt routine continues to time the gap, but blocks in this state.

The STATE_STOP is used a a flag to indicate to the decode routine that a full transmission is available. When processing is done, the resume() method sets the state to STATE_IDLE so the interrupt routine can start recording the next transmission. There are a few things to note here. Gap timing continues during STATE_STOP and STATE_IDLE so an accurate measurement of the time between transmissions can be obtained. If resume() is not called before the next transmission starts, the partial transmission will be discarded. The motivation behind the stop/resume is to ensure the receive buffer is not overwritten while it is still being processed; debugging becomes very difficult if the buffer is constantly changing.

Details of the sending library

The transmission code is straightforward. To ensure accurate output frequencies and duty cycles, I use the PWM timer, rather than delay loops to modulate the output LED at the appropriate frequency. (See my Arduino PWM Secrets article for more details on the PWM timers.) At the low level, enableIROut sets up the timer for PWM output on pin 3 at the proper frequency. The mark() method sends a mark by enabling PWM output and delaying the specified time. The space() method sends a space by disabling PWM output and delaying the specified time.

The IRremote library treats the different protocols as follows:

NEC: 32 bits are transmitted, most-significant bit first. (protocol details)

Sony: 12 or more bits are transmitted, most-significant bit first. Typically 12 or 20 bits are used. Note that the official protocol is least-significant bit first. (protocol details) For more details, I've written an article that describes the Sony protocol in much more detail: Understanding Sony IR remote codes.

RC5: 12 or more bits are transmitted most-significant bit first. The message starts with the two start bits, which are not part of the code values. (protocol details)

RC6: 20 (typically) bits are transmitted, most-significant bit first. The message starts with a leader pulse, and a start bit, which is not part of the code values. The fourth bit is transmitted double-wide, since it is the trailer bit. (protocol details)

For Sony and RC5/6, each transmission must be repeated 3 times as specified in the protocol. The transmission code does not implement the RC5/6 toggle bit; that is up to the caller.

Adding new protocols

Manufacturers have implemented many more protocols than this library supports. Adding new protocols should be straightforward if you look at the existing library code. A few tips: It will be easier to work with a description of the protocol rather than trying to entirely reverse-engineer the protocol. The durations you receive are likely to be longer for marks and shorter for spaces than the protocol suggests. It's easy to be off-by-one with the last bit; the last space may be implicit.

Troubleshooting

To make it easier to debug problems with IR communication, I have optional debugging code in the library. Add #define DEBUG to the beginning of your code to enable debugging output on the serial console. You will need to delete the .o files and/or restart the IDE to force recompilation.

Problems with Transmission

If sending isn't working, first make sure your IR LED is actually transmitting. IR will usually show up on a video camera or cell phone camera, so this is a simple way to check. Try putting the LED right up to the receiver; don't expect a lot of range unless you amplify the output.

The next potential problem is if the receiver doesn't understand the transmitter, for instance if you are sending the wrong data or using the wrong protocol. If you have a remote, use this library to check what data it is sending and what protocol it is using.

An oscilloscope will provide a good view of what the Arduino or a remote is transmitting. You can use an IR photodiode to see what is getting transmitted; connect it directly to the oscilloscope and hold the transmitter right up to the photodiode. If you have an oscilloscope, just connect the oscilloscope to the photodiode. If you don't have an oscilloscope, you can use a sound card oscilloscope program such as xoscope.

The Sony and RC5/6 protocols specify that messages must be sent three times. I have found that receivers will ignore the message if only sent once, but will work if it is sent twice. For RC5/6, the toggle bit must be flipped by the calling code in successive transmissions, or else the receiver may only respond to a code once.

Finally, there may be bugs in this library. In particular, I don't have anything that receives RC5/RC6, so they are untested.

Problems with Receiving

If receiving isn't working, first make sure the Arduino is at least receiving raw codes. The LED on pin 13 of the Arduino will blink when IR is being received. If not, then there's probably a hardware issue.

If the codes are getting received but cannot be decoded, make sure the codes are in one of the supported protocols. If codes should be getting decoded, but are not, some of the measured times are probably not within the 20% tolerance of the expected times. You can print out the minimum and maximum expected values and compare with the raw measured values.

The examples/IRrecvDump sketch will dump out details of the received data. The dump method dumps out these durations but converts them to microseconds, and uses the convention of prefixing a space measurement with a minus sign. This makes it easier to keep the mark and space measurements straight.

IR sensors typically cause the mark to be measured as longer than expected and the space to be shorter than expected. The code extends marks by 100us to account for this (the value MARK_EXCESS). You may need to tweak the expected values or tolerances in this case.

The library does not support simultaneous sending and receiving of codes; transmitting will disable receiving.

Applications

I've used this library for several applications:

Other projects that use this library

Other Arduino IR projects

I was inspired by Building a Universal Remote with an Arduino; this doesn't live up to being a universal remote, but has a lot of information. The NECIRrcv library provided the interrupt handling code I use.

Arc + Arduino + ARM: Temperature monitoring

I'm using my Arc web server running on an ARM-based SheevaPlug to get analog data from my Arduino. The frame below and the graph of temperature and illumination are coming live are a screenshot from the SheevaPlug; they are dynamically generated by some simple Arc code which also collects the data from the Arduino. (Note: this is currently a screenshot, as I'm currently using the SheevaPlug for another project.)
screenshot
The graph shows the daily cycle of illumination (green line), as well as temperature climbing during the day (red line). The temperature goes way, way up when the sun hits the temperature sensor directly. Perhaps I should find some shade for it. For one day, the data went crazy; this is where the wires from the sensor got knocked out of the Arduino by the vacuum cleaner.

The SheevaPlug and Arduino

The Arc web server is running on the ARM-based SheevaPlug, a small Linux server that plugs into the wall. It is connected by USB to an Arduino microcontoller, which does the analog to digital conversion. In the photo, the SheevaPlug also has an Ethernet cable attached. A 4-conductor wire connects the Arduino to the temperature and light sensors outside. This wire is old phone cable, but as described below, I probably should have used something more shielded.

The Arduino code

The Arduino sketch (download) simply reads the voltages and writes them to the serial port:
#define SUPPLY 5.14 // Supply voltage (measured)

void setup() {
  Serial.begin(9600);
}

void loop() {
  float v = analogRead(TEMP_PIN) * SUPPLY / 1024;
  float c = (v - .5) * 100;
  Serial.print(c); 
  Serial.print(" ");
  Serial.println(analogRead(SUN_PIN), DEC);
  delay(5000);
}
Note that I've hardwired the supply voltage, as it's needed for the conversion. The Celsius temperature is obtained directly from the measured voltage (10mV per degree, and offset by .5V to allow negative temperatures).

The Arc code

The Arc server code (download) is straightforward. It leverages my earlier Arc example server code (download).

A background thread fetches the time / sun data lines from the serial port and writes the data to a file. It converts Celsius to Fahrenheit and limits the updates to one per minute:

(def logdata ()
  (w/appendfile outf "/tmp/data"
    (w/stdout outf
      (w/infile serial "/dev/ttyUSB0"
        (let oldtimestamp nil
          (while 1
            (with ((degc sun) (tokens (readline serial))
                  timestamp (gettimestamp))
              (when (isnt timestamp oldtimestamp)
                (let degf (+ 32 (* 9. (/ (coerce degc 'num) 5.)))
               (prn timestamp " " (num degf 2) " " sun)
                  (= oldtimestamp timestamp))))))))))

(new-bgthread 'logdata (fn () (logdata)) 0)
The simple web page is generated in Arc, but the graph itself is generated by gnuplot. Since this is currently a static page, it's a bit of overkill to use the Arc functions to generate the page.
(defop temperature req
  (system "gnuplot < gnuplotcmd")
  (page
    (tag h1 (prn "Temperature and light: Arc + Arduino + ARM"))
    (gentag img src "/graph.png")
    (tag br)
    (prn "This web page is being served by the") (link "Arc language" "http://www.righto.com/doc/index.html") (pr " web server running on a ")
    (link "SheevaPlug" "http://www.righto.com/2009/06/arduino-sheevaplug-cool-hardware.html")
    (pr " plug computer.") (pr "  For more details see ")
    (link "arcfn.com" "http://www.righto.com")
    (pr ".")
    (para)
    (link "View source code for this page" "/source-t")))

Arc vs. Python

I implemented a similar Arduino graph server in Python a few weeks ago. Overall, both Python and Arc make it easy to set up a simple web server. Comparing the Python code with the Arc code reveals Arc's lack of libraries.

The first problem with Arc is it doesn't have a serial library, so I can't configure the baud rate and parameters on my serial port from Arc. I'm just assuming it's set up right, and that's working but not very robust.

The second problem I encountered was creating the timestamps on the data. The latest version of Arc has a timedate function to generate a timestamp but unfortunately that's only in GMT. I tried writing a routine to convert the time to the local timezone, but that got rather annoying. In addition, Arc doesn't have any printf-like formatting, so I had to make my own formatting routine to generate zero-padded strings of the form "12:05". I rapidly decided that writing timezone functions wasn't what I wanted to do, and ended up just using the Unix date command. (This confirm's "kens' law": Any sufficiently complicated Arc application requries the use of 'system to get things done.)

; return a timestamp of the form 2009-08-20 19:22
(= tz "America/Los_Angeles")
(def gettimestamp ()
  (trim (tostring (system (string "TZ=" tz " date +'%m-%d-%Y %H:%M'")))))
I'd have to say that Python is clearly the easier solution overall.

Hardware details

sensors The circuit is pretty trivial. It measures light with a photocell and temperature with a TMP36 temperature sensor (tutorial). (The TMP36 is the three-wire black part that looks like a transistor.) These parts generate voltages that are read by the Arduino's analog-to-digital converters. The temperature sensor's voltage directly gives the Celsius temperature, while the photocell's light measurement is not calibrated to anything.

I had several problems with temperature measurement. First, the Arduino's A/D converter converts relative to its power supply voltage, so the temperature is only as stable as the power supply, and must be manually calibrated. Second, the 10 feet of unshielded phone wire between the Arduino and the temperature sensor introduced a lot of noise. Notice the 10 degree fluctuations on the first day of measurement. I added bypass capacitors after the first day, and the measurements are much smoother. Finally, the temperature sensor heats up a lot when the direct sun hits it in the late afternoon, apparently reaching 140° F. I guess there's a reason why real meteorologists put their temperature sensors in sheltered boxes instead of directly in the sun.

If I were doing this again, I'd probably use a digital temperature sensor such as the One-wire DS18B20; this would avoid the analog calibration and noise issues.

It would be cool to replace the wire between the Arduino and the sensors with Xbee wireless networking. Since I don't have any Xbees, the wire will have to suffice for now.

The photocell voltage is generated from a simple resistor divider. After the second day I changed the resistor from 10K to 1K so the curve wouldn't saturate in the bright sun. (10K worked fine indoors, but outdoors is much brighter.) You can see the break in the green line where I changed resistors.
Schematic

Conclusion

Arc and the SheevaPlug have been more reliable than I expected; my code has been running for a couple of weeks without problems. I think the SheevaPlug makes a good platform for this sort of project. Using Arc, however, is more of an "experimental curiosity"; I'd recommend a different language unless you really want to use Arc.

I have a few other related postings: