I rigged up a couple of attiny85s with a ir diode and this ir receiver:
http://www.sparkfun.com/products/10266
Surprisingly both my transmitter and receiver code worked on my first try!
Transmitter:
// Test transmitter, 38khz modulation, 100ms on, 100ms off
#include <avr/io.h>
#include <util/delay.h>
// width of up and down pulse in ms
#define pulse_width 100
#define FCPU 8000000
#define FMOD 38000
// output pin is PB4, OC1B
void setup_timer(void) {
// Using 8bit timer 1, OCR1B
// CTC1 clears timer on match, CS10 sets clock to FCPU
TCCR1 |= (1 << CTC1) | (1 << CS10);
// Set compare registers
OCR1C = 1 + (FCPU/FMOD); // 211, triggers CTC
OCR1B = FCPU/FMOD; // 210, trigger OC1B match
// COM1B1 = 0 & COM1B0 = 1 toggles OC1B on match
GTCCR |= (1 << COM1B0);
// Enable timer/counter 1
PLLCSR |= (1 << PLLE);
}
int main(void) {
setup_timer();
PORTB |= (1 << PB4); // debugging
for (;;) {
// Wait pulse_width
_delay_ms(pulse_width);
// Toggle pin output enable
DDRB ^= (1 << PB4);
}
}
Receiver:
// Test receiver, toggle lights on high and low pulse
#include <avr/io.h>
#include <util/delay.h>
// PB0 = sensor input
// PB3 = green led
// PB4 = red led
int main(void) {
// Digital direction out, out, in
DDRB = (1 << PB4) | (1 << PB3) | ~(1 << PB0);
// Enable pull-up on sensor port
PORTB = (1 << PB0);
for (;;) {
if (PINB & (1 << PB0)) { // Red on, green off
// If pin is high then there is no signal
PORTB |= (1 << PB4);
PORTB &= ~(1 << PB3);
} else { // Green on, red off
// If pin is low then there is a signal
PORTB |= (1 << PB3);
PORTB &= ~(1 << PB4);
}
_delay_ms(5);
}
}
Of course for a proper receiver you would probably setup an interrupt to watch for a start bit and set a variable to tell the mainloop to stop and receive instructions.
A proper transmitter is trickier. I guess you need to setup some kind of timing scheme, and to use short vs. long pulses to signal 0/1? For my application I only need 4 bits of data intermittently to signal mode changes based on button presses. Signaling a held button without a full transmission would be cool too. Maybe something like a double long pulse?
I’m sure there is a better way to setup timers/PWM to produce 38kHz, but there are so many ways to setup the timers on these things… Any suggestions are welcome.