Jan 16 2011

IR remote control of servo using Arduino

Got a little bit done of the control for the sound system… I wasn’t getting good results from the Sharp GP1U5 module I was using until I stumbled upon some work by Ken Shirriff. He has written an IRremote library that supports both sending and receiving and includes support for a few different protocols.

The supported protocols don’t seem to cover the remotes I’m playing with, but luckily, he also did a post on handling arbitrary remotes by generating a hash value. Using that as a starting point, I cobbled together a fairly simple proof of concept sketch.

/*
* IR Remote controlled servo
*
*
*
* IR Remote code from Ken Shirriff (www.arcfn.com), specifically this post:
* http://www.arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html
*/

#include
#include

Servo myservo; // create servo object to control a servo
// a maximum of eight servo objects can be created

#define LEDPIN 13

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

int volume = 0;
int max_volume = 180; // determined by max position of the servo
int mute = 0;

void setup()
{
irrecv.enableIRIn(); // Start the receiver

myservo.attach(9,600,2400); // attaches the servo on pin 9 to the servo object with pulse widths for Hitec
// servo

myservo.write(0); // tell servo to go to base position
delay(1000);

Serial.begin(9600);
}

// Compare two tick values, returning 0 if newval is shorter,
// 1 if newval is equal, and 2 if newval is longer
// Use a tolerance of 20%
int compare(unsigned int oldval, unsigned int newval) {
if (newval < oldval * .8) {
return 0;
}
else if (oldval < newval * .8) {
return 2;
}
else {
return 1;
}
}

// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
#define FNV_PRIME_32 16777619
#define FNV_BASIS_32 2166136261

/* Converts the raw code values into a 32-bit hash code.
* Hopefully this code is unique for each button.
*/
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;
}

void loop() {
if (irrecv.decode(&results)) {
unsigned long hash = decodeHash(&results);
switch (hash) {
case 0x4B12992B: // Vol Up
case 0x22D912B8:
Serial.println("Volume Up");
volume += 1;
if ( mute == 1 ) {
volume -= 1;
mute = 0;
}
break;
case 0x1BE8C80D: // Vol Down
case 0x776C6E79:
Serial.println("Volume Down");
volume -= 1;
if ( mute == 1 ) {
volume += 1;
mute = 0;
}
break;
case 0x92DFD41C:
Serial.println("Mute");
mute = 1;
break;
default:
Serial.print("'real' decode: ");
Serial.print(results.value, HEX);
Serial.print(", hash decode: ");
Serial.println(hash, HEX);
}
irrecv.resume(); // Resume decoding (necessary!)
if ( volume < 0 ) { volume = 0; };
if ( volume > max_volume ) { volume = max_volume; }
if ( mute == 1 ) {
myservo.write(0);
}
else {
myservo.write(volume);
}
}
}

I’m using a Hitec HS-325HB servo with this code, and I implemented volume controlling from two different remotes I had kicking around – only one had a mute button.

Mute is handled by moving the servo to the zero position, and the next volume up/down will unmute by returning the servo to the correct position.

With the Arduino side basically figured out, the next step is to figure out the best way to tie the volume control and Arduino together. One potential problem is that with the servo hooked up, turning the volume control manually will probably not be possible. I’ll probably add a mute button and up/down buttons to allow control without needing to find the remote control. Doing that should be simple enough, and make it a lot more user friendly.


Jan 15 2011

Playing with Arduino

I finally managed to start playing with the Arduino again – I’ve had one for a couple years, and played with it a bit as soon as I got it, but then it sat on my shelf of unfinished projects.

My collection actually has three Arduinos – one is a Freeduino with a USB interface, and the other two are intended for use on a breadboard (a Boarduino and a Bare Bones Board). For a while, I’ve been intending to use the Freeduino to program the chips on the other boards since I don’t have the right cable to connect them otherwise, but I hadn’t realized that on the arduino.cc site, they actually have instructions for doing that. In addition, they show the most minimal setup possible – which only requires an AVR, a resistor, a capacitor and a few wires if you use the internal oscillator. How much else you need depends on what you are using the Arduino for, but it certainly makes the idea of embedding the Arduino in a project more interesting since it drops the base cost under $10.

I’m currently playing with two projects – reading a SD card, and controlling a servo. The SD card is to see if a ‘dead’ card that a friend has can be accessed via SPI. I’m assuming that the typical USB readers use something other than SPI since that is a slower mode of access, and is optional on microSD cards. I’m going to set up a breadboard with a circuit to access my test card (a 32 Mb Canon card) until I get a chance to pick up a 74AHC125. The issue is that SD cards run at 3.3V, while the Arduino is at 5V. I can use a resistor divider setup to interface to SD cards, but if I want to support SDHC cards, I need to be able to meet the 10ns risetime requirements in the spec, which the 74AHC125 should manage.

The servo is going to be controlled by the Arduino via an IR remote. I have an IR receiver module that keeps things simple – feed it power and it spits out a clean signal that you can connect to the Arduino. From there you need to decode the pulses to figure out what key was pressed, and take appropriate action.

As far as the servo goes, I have never used one before, so when I hooked one up today, I wasn’t sure how difficult it was going to be. There is a sample sketch that is provided with the Arduino IDE that sweeps the servo back and forth, and I loaded it up on the Arduino and expected to see some motion. No such luck…. no motion at all. I checked with Google, and found some forums where other people were having trouble, but nothing that appeared to be my problem.

Then I did a check on my setup – power and ground hooked up? Check. Control signal? Check. Servo voltage of 5V enough to drive it? Yup. Control signal hooked up to the right Arduino pin? Uh-huh. I finally tracked the problem down to the jumper wires I had used to connect everything. I had soldered some pins to each end of some lengths of wire to make it easy to get a good connection with the stranded wire I was using – unfortunately, the control wire had a bit of extra solder on the one side. And wouldn’t you know it, that was the side that was facing the power connection. I had a short between 5V and the control signal, so as far as the servo was concerned, there was no control signal.

Once I fixed that little issue, the servo started turning back and forth as expected. Now all I have to do is remember how to decode the IR input and make it control the servo. That shouldn’t be very hard, should it? In any case, I’m going to play with it tomorrow and see where I get. I’ll try real hard to do a decent write-up if I manage to get it working – same for the SD card reader….


May 17 2009

Rare Earth Magnets to the rescue

Just found another thing rare earth magnets are good for – fishing wires at a 90 degree angle….

Normally, if I’m trying to run wires, I use fish tape (also known as a draw wire or draw tape). It works great if you are trying to run stuff through conduit, or in a fairly straight line. Where it doesn’t work so well is if you are trying to go around a corner.

In the past, my solution has been to feed in wires from both sides with hooks bent at the ends, and try and hook them together. It generally works after a lot of attempts, a lot of swearing and a lot of frustration.

Today, I had the bright idea of using rare earth magnets to make the process a whole lot easier…. one goes on the end of a string that gets dropped through the vertical access, the other on a rigid pipe or stick that is fed in the horizontal one. Get the two close to each other, and ‘click’, they are attached and you can pull the string out with the stick. If you need to feed up and over, just use an appropriate length of pipe, and wire instead of string (since it’s hard to feed string through a pipe). The wire can be fed through the pipe, and you can use the pipe to lift the magnet into position. Once the two magnets have made contact, the pipe can be lowered – the wire will pull through the pipe and you can then pull that through as before.