*unofficial* FIRST IR module driver released

UNOFFICIAL CONTENT. This code was not written by IFI or FIRST.

Well, thanks to the Holly Area School system, I got bored and wrote some alpha (for now) code that should let anyone with MPLAB interface to the new FIRST IR receiver module.

I don’t even know if the thing works right now, since I have not been to the shop and don’t have a board yet. But, I’m pretty sure this can help teams interested in doing the same who have their board.

Figuring out how to hook it up is up to you for now. The white wire goes to the CMD wire for that input, and black goes to ground. Power it off a PWM output with the backup battery, unless you really know what you are doing and can stabilize the voltage from the main battery–just be sure to keep the backup battery charged, or you will see strange behavior.

Let me know if you have any suggestions/concerns/problems/questions and I’ll try to address them.

Here’s the goods:

It’ll be listed on our index as soon as I lose the laziness from today being a snow day.



I saw in your code that you’re restricting the inputs to IOs 1-6 because they have selectable pullup resistors. This isn’t necessary. The outputs of the IR board can sink 8.5mA when driven low, which is easily enough to counteract any pullup resistor. Admittedly, this would be a problem if the IR outputs went to High-Z when there wasn’t a signal, but i think it’s safe to assume that as long as they have power, they’re driving the outputs between high and low and thus you don’t have to worry about pullups.

I didn’t exactly understand that in the spec sheet–I’m obviously missing a few concepts electrically. You are saying that when the IR board drives its pins low, it won’t have a problem with the resistors. It makes sense now that you’ve pointed it out…in pretty much the same words as the spec sheet.:stuck_out_tongue:

Admittedly, this would be a problem if the IR outputs went to High-Z when there wasn’t a signal

Curiosity drives me to ask this: What exactly is High-Z? Does that mean the pins would go to high resistance (seen it called impedance) instead of driving them to ground?

All right, I’ll make the changes. I was hoping to be able to do something like that–I don’t want to mess with configuration bits like that, because I don’t want to change the function of other code that relies on the pullups.

Thanks for your expertise, because, obviously I just don’t have it. Yet. And I’m not supposed to, being that I’m a high school senior…:smiley:

Maybe someday. MI Tech, here I come…

Nice code.

But uhm, why does this need a ‘driver’ per se? Doesn’t it just drive a pin high if a code is recognized? Just like reading buttons from the OI pannel or waiting for a limit switch?

-q :confused:

You’re correct, and I admit that’s why it was so easy to write, but if this is doing something sophisticated on the robot, like adding 30 degrees to the position of an arm, it is easier to use these files because they have a little bit of brain to them–they will only give a 1 once per command, whereas if you printed out the value of the digital input, you would get something like (0,1,1,1,1,1,1,0,0,1,1 etc.). If you print the return value of IR_CommandReceived, you will get something like–to use the same example as earlier-- (0,1,0,0,0,0,0,0,0,1,0 etc.). It makes code look a little nicer, too.

Just figured I’d throw this out there. I really don’t care if anyone uses it or not. At this point, if the rules stay the same as last year’s, I’ll have to re-write it come 1/5/08. Hopefully they change the programming/build window rule up a bit.


Powering a micro controller with an unregulated supply off of the 12v battery that will be driving motors and firing relays will be unreliable and possibly damaging. The voltage will be unstable, which would make readings unpredictable. Noise in the power supplied to the device can also cause the device to reset or freeze constantly. If the device becomes damaged, it is entirely possible that there would be the same effect as hooking up the digital inputs directly to the battery.

To power this device while attached to the robot, it would be wise to design a power supply. See Voltage regulator - Wikipedia for a starting point. To connect this device to the robot controller, it would be wise to use opto-isolators/optocouplers to protect the devices from each other. See Opto-isolator - Wikipedia for more information.


Yes, High-Z means exactly that.

(Gross oversimplification to follow)

Typically, digital outputs come in two general flavors, two-state and tri-state. Two state outputs either drive a pin to high voltage, or drive a pin two low voltage as you seem familiar with. Tri-state outputs have this third additional state called High-Z where the output is at a high resistance. This only becomes important or even necessary if you have two outputs both wired to the same input. If you want them both to reliably drive the input at different times, you can’t just assume that driving output A low will let output B signal high and low reliably. That would depend entirely on the resistances of the traces an a host of other factors that might not stand still over time. In most cases it wouldn’t ever work, period, and the input would always see a low voltage. So, instead, you put output A into a High-Z state and it no longer affects the signal because no current is passing through it. (To a first order approximation)

(End oversimplification)

That’s all ignoring the host of other output styles available and a lot of other issues, but that’s the gist of the purpose of a High-Z state. It’s simply to more or less remove that particular output from the circuit that’s driving the input.

Pull-up resistors serve a slightly different function. Without a pull-up resistor, an input with nothing connected to it isn’t in any well defined state and might, in fact, fluctuate wildly between high and low states. With the pull-up (or down in some cases) resistor, if there isn’t an active device sourcing or sinking current on the other end of the circuit, a trickle of current flows through the pull-up resistor giving more or less 0 volts of drop across the resistor, meaning the input is at (high) volts. When the circuit is sinking current to ground either through a dead short like a limit switch or via a digital output like on the IR module, the pull-up resistor ends up making a voltage divider with the short or digital output. Since the resistor is such a high value (100k) the 5V contributes little to the final voltage at the input, and you end up with ~(low) volts at the input. The main reason for turning off pull-up resistors is that they can slightly slow down logic transitions and introduce noise from the power supply into the digital input.

For all this and more, I heartily recommend “The Art of Electronics” by Horowitz and Hill. It’s a bit thick and expensive and the '89 2nd edition is a little dated… but a new edition is set for March and the do a rather good job of introducing things with as little math as possible at first to help you get a good feel for it.

According to the “The board contains an IR sensor, a CMOS microcontroller, a 5V voltage regulator,…”

No additional power supply should be needed. That is why section 6 states,

6 Operating Voltage, Output Current
6.1 Operating voltage range
The onboard voltage regulator needs at least 7 volts DC, and can accept more than 15 volts. To avoid
problems, a reasonably clean voltage source is recommended to power this board. Avoid having any noise
glitches on this supply that go below 7 volts DC.”

I would agree, running it from the main +12 V battery may be a little risky, but running it from the 7.2Vdc backup adds an additional load to that battery that will need to be accounted for. So, how do you handle this???
As long as the rules will allow it, use a large mAh battery for the backup, say 1500mAh???

I haven’t reviewed the code fully yet, but I do have a comment about style.
You have written the following:

//If we're in debug mode, include stdio.h for printf.
	#include <stdio.h>

//then, somewhere in the body..

		printf("FIRSTIR:" ... );

A) You do not need to put an include guard on stdio. There is an include guard defined in its header file already, and as soon as you include it in any file it should be in your compilation unit. Plus, it only takes a fraction of a second to compile it anyway.
B) Instead of having to type preprocessor If’s all the time, you can consolidate your printf’s with something like this…

In the .h file:

#define IR_DEBUG	1

#ifdef IR_DEBUG
   #define IRDEBUG(S,A,B,C,D) printf(S,A,B,C,D)
   #define IRDEBUG(S,A,B,C,D) ;

In the .c file (whenever you want to print a debug statement.):

IRDEBUG("FIRSTIR: CMD Inputs...0: %d, 1: %d, 2: %d, 3: %d

This should clean up your code a bit, and will give you the same ease of use.

this may be a really foolish question,
but if you look at the page for the documentation on the sensor(http://www.usfirst.org/uploadedFiles/Community/FRC/FRC_Documents_and_Updates/2008_Assets/FIRSTIR%20-%20Instructions%20_121007.pdf), it looks like you have to physically push a button to program the ir chip, and thus the sensor will be learning a code prior to the match,
and thus there is no need for code to receive the ir pattern
as the code is stored in the chip

i believe that based on this what is going to happens is that each team will be given an ir pattern at the beginning of the match, and then will complete a goal using that code

The code is stored in the chip onboard the IR sensor, but what are the outputs connected to? For the purposes of this code, I assumed we are connecting the outputs to the digital inputs of the robot. This code doesn’t receive the actual pattern of pulses from the remote, but it can tell which pre-learned command has been received.

At this point, this code has been written on the assumptions that a) FIRST is not changing the controller this year, and b) we actually are using this sensor on the robot. Both conditions are guesses, so this piece of software may be totally useless for the 08 season. We’ll see.

Thanks for the style hints, Tom. If you have any more, I’d love to hear them. After writing these files, it seems they are kind of…messy. But I tried my best with the limited knowledge I have, and that’s all I can hope to do.


You seem to disagree that a better power supply is needed, but then cite exactly why a better power supply is needed, so I’m confused.
If the device is running in and of itself, connected to nothing but a battery like the KOP backup battery, then the voltage supplied by the battery would be sufficiently clean for the simple regulator (that is onboard the device) to power the device.
If the device is being powered by the 12v battery of a complete robot, there are many other noisy loads on it that can easily drop the voltage below 7 volts for however short a time. That is probably enough to cause a problem for the embedded micro controller if it is anything like any other PIC that I’ve worked with.
So I would probably add another stage of voltage regulation just like the regulator circuit on the device, but with larger capacitors and think that would probably be fine, but I’m not so confident in that idea as to post it as a solution.

Well, since the board has a 7805 linear regulator on it, simply throw a large noise filter capacitor on it, and run it off the main battery. The capacitors will keep the voltage at a steadyish 12v, and the 7805 will burn off the rest of the voltage as heat.

Your confusion is well founded. I did contradict myself, a bit. I guess what I was trying to say is that the regulator onboard will work fine until the supply voltage dips below ~7vdc, and as you point out, for no matter how short a time. At that point, it is worthless.
Honestly, I don’t know if adding a couple caps is legal, but it certainly would provide the filtering needed, assuming they were large enough. So, instead of advising adding more caps, I opted for using a more robust power source. The backup battery will have enough power as long as it has enough capacity. As of last year, a larger backup battery was within the rules, as long as you charged it from the KOP charger.